exec-ddl
CREATE TABLE abc (
  a CHAR PRIMARY KEY,
  b FLOAT,
  c BOOLEAN,
  d DECIMAL
)
----
TABLE abc
 ├── a string not null
 ├── b float
 ├── c bool
 ├── d decimal
 └── INDEX primary
      └── a string not null

exec-ddl
CREATE TABLE xyz (
  x INT PRIMARY KEY,
  y INT,
  z FLOAT,
  INDEX xy (x, y),
  INDEX zyx (z, y, x),
  INDEX yy (y)
)
----
TABLE xyz
 ├── x int not null
 ├── y int
 ├── z float
 ├── INDEX primary
 │    └── x int not null
 ├── INDEX xy
 │    ├── x int not null
 │    └── y int
 ├── INDEX zyx
 │    ├── z float
 │    ├── y int
 │    └── x int not null
 └── INDEX yy
      ├── y int
      └── x int not null

exec-ddl
CREATE TABLE kuvw (
  k INT PRIMARY KEY,
  u INT,
  v INT,
  w INT,

  INDEX uvw(u,v,w),
  INDEX wvu(w,v,u),
  INDEX vw(v,w) STORING (u),
  INDEX w(w) STORING (u,v)
)
----
TABLE kuvw
 ├── k int not null
 ├── u int
 ├── v int
 ├── w int
 ├── INDEX primary
 │    └── k int not null
 ├── INDEX uvw
 │    ├── u int
 │    ├── v int
 │    ├── w int
 │    └── k int not null
 ├── INDEX wvu
 │    ├── w int
 │    ├── v int
 │    ├── u int
 │    └── k int not null
 ├── INDEX vw
 │    ├── v int
 │    ├── w int
 │    ├── k int not null
 │    └── u int (storing)
 └── INDEX w
      ├── w int
      ├── k int not null
      ├── u int (storing)
      └── v int (storing)

# --------------------------------------------------
# ReplaceMinWithLimit
# --------------------------------------------------

opt
SELECT min(a) FROM abc
----
scalar-group-by
 ├── columns: min:5(string)
 ├── cardinality: [1 - 1]
 ├── key: ()
 ├── fd: ()-->(5)
 ├── scan abc
 │    ├── columns: a:1(string!null)
 │    ├── limit: 1
 │    ├── key: ()
 │    └── fd: ()-->(1)
 └── aggregations
      └── const-agg [type=string, outer=(1)]
           └── variable: a [type=string]

# Verify the rule still fires even if DISTINCT is used.
opt
SELECT min(DISTINCT a) FROM abc
----
scalar-group-by
 ├── columns: min:5(string)
 ├── cardinality: [1 - 1]
 ├── key: ()
 ├── fd: ()-->(5)
 ├── scan abc
 │    ├── columns: a:1(string!null)
 │    ├── limit: 1
 │    ├── key: ()
 │    └── fd: ()-->(1)
 └── aggregations
      └── const-agg [type=string, outer=(1)]
           └── variable: a [type=string]

opt
SELECT min(b) FROM abc
----
scalar-group-by
 ├── columns: min:5(float)
 ├── cardinality: [1 - 1]
 ├── key: ()
 ├── fd: ()-->(5)
 ├── scan abc
 │    └── columns: b:2(float)
 └── aggregations
      └── min [type=float, outer=(2)]
           └── variable: b [type=float]

opt
SELECT min(y) FROM xyz where z=7
----
scalar-group-by
 ├── columns: min:4(int)
 ├── cardinality: [1 - 1]
 ├── key: ()
 ├── fd: ()-->(4)
 ├── scan xyz@zyx
 │    ├── columns: y:2(int!null) z:3(float!null)
 │    ├── constraint: /3/2/1: (/7.0/NULL - /7.0]
 │    ├── limit: 1
 │    ├── key: ()
 │    └── fd: ()-->(2,3)
 └── aggregations
      └── const-agg [type=int, outer=(2)]
           └── variable: y [type=int]

# ReplaceMaxWithLimit has the same behavior with max() as
# the previous min() query because z is the prefix of a unique key
opt
SELECT max(y) FROM xyz where z=7
----
scalar-group-by
 ├── columns: max:4(int)
 ├── cardinality: [1 - 1]
 ├── key: ()
 ├── fd: ()-->(4)
 ├── scan xyz@zyx,rev
 │    ├── columns: y:2(int!null) z:3(float!null)
 │    ├── constraint: /3/2/1: (/7.0/NULL - /7.0]
 │    ├── limit: 1(rev)
 │    ├── key: ()
 │    └── fd: ()-->(2,3)
 └── aggregations
      └── const-agg [type=int, outer=(2)]
           └── variable: y [type=int]

# We expect ReplaceMinWithLimit not to be preferred here.
# This is because we know nothing about the ordering of y
# on the index xy after a scan on xy with x>7.
opt
SELECT min(y) FROM xyz WHERE x>7
----
scalar-group-by
 ├── columns: min:4(int)
 ├── cardinality: [1 - 1]
 ├── key: ()
 ├── fd: ()-->(4)
 ├── scan xyz@xy
 │    ├── columns: x:1(int!null) y:2(int)
 │    ├── constraint: /1/2: [/8 - ]
 │    ├── key: (1)
 │    └── fd: (1)-->(2)
 └── aggregations
      └── min [type=int, outer=(2)]
           └── variable: y [type=int]

# We expect ReplaceMaxWithLimit not to be preferred here.
# This is because we know nothing about the ordering of y
# on the index xy after a scan on xy with x>7
opt
SELECT max(y) FROM xyz WHERE x>7
----
scalar-group-by
 ├── columns: max:4(int)
 ├── cardinality: [1 - 1]
 ├── key: ()
 ├── fd: ()-->(4)
 ├── scan xyz@xy
 │    ├── columns: x:1(int!null) y:2(int)
 │    ├── constraint: /1/2: [/8 - ]
 │    ├── key: (1)
 │    └── fd: (1)-->(2)
 └── aggregations
      └── max [type=int, outer=(2)]
           └── variable: y [type=int]

opt
SELECT max(x) FROM xyz
----
scalar-group-by
 ├── columns: max:4(int)
 ├── cardinality: [1 - 1]
 ├── key: ()
 ├── fd: ()-->(4)
 ├── scan xyz@xy,rev
 │    ├── columns: x:1(int!null)
 │    ├── limit: 1(rev)
 │    ├── key: ()
 │    └── fd: ()-->(1)
 └── aggregations
      └── const-agg [type=int, outer=(1)]
           └── variable: x [type=int]

opt
SELECT min(x) FROM xyz
----
scalar-group-by
 ├── columns: min:4(int)
 ├── cardinality: [1 - 1]
 ├── key: ()
 ├── fd: ()-->(4)
 ├── scan xyz@xy
 │    ├── columns: x:1(int!null)
 │    ├── limit: 1
 │    ├── key: ()
 │    └── fd: ()-->(1)
 └── aggregations
      └── const-agg [type=int, outer=(1)]
           └── variable: x [type=int]

opt
SELECT min(x) FROM xyz WHERE x in (0, 4, 7)
----
scalar-group-by
 ├── columns: min:4(int)
 ├── cardinality: [1 - 1]
 ├── key: ()
 ├── fd: ()-->(4)
 ├── scan xyz@xy
 │    ├── columns: x:1(int!null)
 │    ├── constraint: /1/2: [/0 - /0] [/4 - /4] [/7 - /7]
 │    ├── limit: 1
 │    ├── key: ()
 │    └── fd: ()-->(1)
 └── aggregations
      └── const-agg [type=int, outer=(1)]
           └── variable: x [type=int]

opt
SELECT max(x) FROM xyz WHERE x in (0, 4, 7)
----
scalar-group-by
 ├── columns: max:4(int)
 ├── cardinality: [1 - 1]
 ├── key: ()
 ├── fd: ()-->(4)
 ├── scan xyz@xy,rev
 │    ├── columns: x:1(int!null)
 │    ├── constraint: /1/2: [/0 - /0] [/4 - /4] [/7 - /7]
 │    ├── limit: 1(rev)
 │    ├── key: ()
 │    └── fd: ()-->(1)
 └── aggregations
      └── const-agg [type=int, outer=(1)]
           └── variable: x [type=int]

opt
SELECT min(y) FROM xyz
----
scalar-group-by
 ├── columns: min:4(int)
 ├── cardinality: [1 - 1]
 ├── key: ()
 ├── fd: ()-->(4)
 ├── scan xyz@yy
 │    ├── columns: y:2(int!null)
 │    ├── constraint: /2/1: (/NULL - ]
 │    ├── limit: 1
 │    ├── key: ()
 │    └── fd: ()-->(2)
 └── aggregations
      └── const-agg [type=int, outer=(2)]
           └── variable: y [type=int]

opt
SELECT min(y), min(y) FROM xyz
----
scalar-group-by
 ├── columns: min:4(int) min:4(int)
 ├── cardinality: [1 - 1]
 ├── key: ()
 ├── fd: ()-->(4)
 ├── scan xyz@yy
 │    ├── columns: y:2(int!null)
 │    ├── constraint: /2/1: (/NULL - ]
 │    ├── limit: 1
 │    ├── key: ()
 │    └── fd: ()-->(2)
 └── aggregations
      └── const-agg [type=int, outer=(2)]
           └── variable: y [type=int]

# ReplaceMinWithLimit does not apply when there is
# a grouping column
opt
SELECT min(y) FROM xyz GROUP BY y
----
project
 ├── columns: min:4(int)
 └── group-by
      ├── columns: y:2(int) min:4(int)
      ├── grouping columns: y:2(int)
      ├── internal-ordering: +2
      ├── key: (2)
      ├── fd: (2)-->(4)
      ├── scan xyz@yy
      │    ├── columns: y:2(int)
      │    └── ordering: +2
      └── aggregations
           └── min [type=int, outer=(2)]
                └── variable: y [type=int]

# ReplaceMaxWithLimit does not apply when there is
# a grouping column
opt
SELECT max(y) FROM xyz GROUP BY y
----
project
 ├── columns: max:4(int)
 └── group-by
      ├── columns: y:2(int) max:4(int)
      ├── grouping columns: y:2(int)
      ├── internal-ordering: +2
      ├── key: (2)
      ├── fd: (2)-->(4)
      ├── scan xyz@yy
      │    ├── columns: y:2(int)
      │    └── ordering: +2
      └── aggregations
           └── max [type=int, outer=(2)]
                └── variable: y [type=int]

# ReplaceMinWithLimit does not apply when there is
# a grouping column
opt
SELECT min(y) FROM xyz GROUP BY x
----
project
 ├── columns: min:4(int)
 └── group-by
      ├── columns: x:1(int!null) min:4(int)
      ├── grouping columns: x:1(int!null)
      ├── internal-ordering: +1
      ├── key: (1)
      ├── fd: (1)-->(4)
      ├── scan xyz@xy
      │    ├── columns: x:1(int!null) y:2(int)
      │    ├── key: (1)
      │    ├── fd: (1)-->(2)
      │    └── ordering: +1
      └── aggregations
           └── min [type=int, outer=(2)]
                └── variable: y [type=int]

# ReplaceMinWithLimit does not apply on multiple aggregations
# on different columns
opt
SELECT min(y), min(x) FROM xyz
----
scalar-group-by
 ├── columns: min:4(int) min:5(int)
 ├── cardinality: [1 - 1]
 ├── key: ()
 ├── fd: ()-->(4,5)
 ├── scan xyz@xy
 │    ├── columns: x:1(int!null) y:2(int)
 │    ├── key: (1)
 │    └── fd: (1)-->(2)
 └── aggregations
      ├── min [type=int, outer=(2)]
      │    └── variable: y [type=int]
      └── min [type=int, outer=(1)]
           └── variable: x [type=int]


# ReplaceMaxWithLimit does not apply on multiple aggregations
# on different columns
opt
SELECT max(y), max(x) FROM xyz
----
scalar-group-by
 ├── columns: max:4(int) max:5(int)
 ├── cardinality: [1 - 1]
 ├── key: ()
 ├── fd: ()-->(4,5)
 ├── scan xyz@xy
 │    ├── columns: x:1(int!null) y:2(int)
 │    ├── key: (1)
 │    └── fd: (1)-->(2)
 └── aggregations
      ├── max [type=int, outer=(2)]
      │    └── variable: y [type=int]
      └── max [type=int, outer=(1)]
           └── variable: x [type=int]

# ReplaceMinWithLimit does not apply with
# multiple grouping columns
opt
SELECT x,min(y) FROM xyz GROUP BY x,y
----
group-by
 ├── columns: x:1(int!null) min:4(int)
 ├── grouping columns: x:1(int!null)
 ├── internal-ordering: +1
 ├── key: (1)
 ├── fd: (1)-->(4)
 ├── scan xyz@xy
 │    ├── columns: x:1(int!null) y:2(int)
 │    ├── key: (1)
 │    ├── fd: (1)-->(2)
 │    └── ordering: +1
 └── aggregations
      └── min [type=int, outer=(2)]
           └── variable: y [type=int]

# ReplaceMaxWithLimit does not apply with
# multiple grouping columns
opt
SELECT x,max(y) FROM xyz GROUP BY x,y
----
group-by
 ├── columns: x:1(int!null) max:4(int)
 ├── grouping columns: x:1(int!null)
 ├── internal-ordering: +1
 ├── key: (1)
 ├── fd: (1)-->(4)
 ├── scan xyz@xy
 │    ├── columns: x:1(int!null) y:2(int)
 │    ├── key: (1)
 │    ├── fd: (1)-->(2)
 │    └── ordering: +1
 └── aggregations
      └── max [type=int, outer=(2)]
           └── variable: y [type=int]

# ReplaceMinWithLimit does not apply to non-scalar
# aggregates
opt
SELECT min(x), count(y) FROM xyz GROUP BY x,y
----
project
 ├── columns: min:4(int) count:5(int)
 └── group-by
      ├── columns: x:1(int!null) min:4(int) count:5(int)
      ├── grouping columns: x:1(int!null)
      ├── internal-ordering: +1
      ├── key: (1)
      ├── fd: (1)-->(4,5)
      ├── scan xyz@xy
      │    ├── columns: x:1(int!null) y:2(int)
      │    ├── key: (1)
      │    ├── fd: (1)-->(2)
      │    └── ordering: +1
      └── aggregations
           ├── min [type=int, outer=(1)]
           │    └── variable: x [type=int]
           └── count [type=int, outer=(2)]
                └── variable: y [type=int]

# ReplaceMaxWithLimit does not apply to non-scalar
# aggregates
opt
SELECT max(x), count(y) FROM xyz GROUP BY x,y
----
project
 ├── columns: max:4(int) count:5(int)
 └── group-by
      ├── columns: x:1(int!null) max:4(int) count:5(int)
      ├── grouping columns: x:1(int!null)
      ├── internal-ordering: +1
      ├── key: (1)
      ├── fd: (1)-->(4,5)
      ├── scan xyz@xy
      │    ├── columns: x:1(int!null) y:2(int)
      │    ├── key: (1)
      │    ├── fd: (1)-->(2)
      │    └── ordering: +1
      └── aggregations
           ├── max [type=int, outer=(1)]
           │    └── variable: x [type=int]
           └── count [type=int, outer=(2)]
                └── variable: y [type=int]

memo
SELECT min(a) FROM abc
----
memo (optimized, ~4KB, required=[presentation: min:5])
 ├── G1: (scalar-group-by G2 G3 cols=()) (scalar-group-by G4 G5 cols=())
 │    └── [presentation: min:5]
 │         ├── best: (scalar-group-by G4 G5 cols=())
 │         └── cost: 1.10
 ├── G2: (scan abc,cols=(1))
 │    ├── [ordering: +1]
 │    │    ├── best: (scan abc,cols=(1))
 │    │    └── cost: 1050.02
 │    └── []
 │         ├── best: (scan abc,cols=(1))
 │         └── cost: 1050.02
 ├── G3: (aggregations G6)
 ├── G4: (limit G2 G7 ordering=+1) (scan abc,cols=(1),lim=1)
 │    └── []
 │         ├── best: (scan abc,cols=(1),lim=1)
 │         └── cost: 1.07
 ├── G5: (aggregations G8)
 ├── G6: (min G9)
 ├── G7: (const 1)
 ├── G8: (const-agg G9)
 └── G9: (variable a)

memo
SELECT min(b) FROM abc
----
memo (optimized, ~5KB, required=[presentation: min:5])
 ├── G1: (scalar-group-by G2 G3 cols=()) (scalar-group-by G4 G5 cols=())
 │    └── [presentation: min:5]
 │         ├── best: (scalar-group-by G2 G3 cols=())
 │         └── cost: 1060.04
 ├── G2: (scan abc,cols=(2))
 │    ├── [ordering: +2]
 │    │    ├── best: (sort G2)
 │    │    └── cost: 1269.35
 │    └── []
 │         ├── best: (scan abc,cols=(2))
 │         └── cost: 1050.02
 ├── G3: (aggregations G6)
 ├── G4: (limit G7 G8 ordering=+2)
 │    └── []
 │         ├── best: (limit G7="[ordering: +2]" G8 ordering=+2)
 │         └── cost: 1276.90
 ├── G5: (aggregations G9)
 ├── G6: (min G10)
 ├── G7: (select G2 G11)
 │    ├── [ordering: +2]
 │    │    ├── best: (sort G7)
 │    │    └── cost: 1276.88
 │    └── []
 │         ├── best: (select G2 G11)
 │         └── cost: 1060.03
 ├── G8: (const 1)
 ├── G9: (const-agg G10)
 ├── G10: (variable b)
 ├── G11: (filters G12)
 ├── G12: (is-not G10 G13)
 └── G13: (null)

memo
SELECT max(a) FROM abc
----
memo (optimized, ~4KB, required=[presentation: max:5])
 ├── G1: (scalar-group-by G2 G3 cols=()) (scalar-group-by G4 G5 cols=())
 │    └── [presentation: max:5]
 │         ├── best: (scalar-group-by G4 G5 cols=())
 │         └── cost: 1.10
 ├── G2: (scan abc,cols=(1))
 │    ├── [ordering: -1]
 │    │    ├── best: (scan abc,rev,cols=(1))
 │    │    └── cost: 1149.68
 │    └── []
 │         ├── best: (scan abc,cols=(1))
 │         └── cost: 1050.02
 ├── G3: (aggregations G6)
 ├── G4: (limit G2 G7 ordering=-1) (scan abc,rev,cols=(1),lim=1(rev))
 │    └── []
 │         ├── best: (scan abc,rev,cols=(1),lim=1(rev))
 │         └── cost: 1.07
 ├── G5: (aggregations G8)
 ├── G6: (max G9)
 ├── G7: (const 1)
 ├── G8: (const-agg G9)
 └── G9: (variable a)

memo
SELECT max(b) FROM abc
----
memo (optimized, ~5KB, required=[presentation: max:5])
 ├── G1: (scalar-group-by G2 G3 cols=()) (scalar-group-by G4 G5 cols=())
 │    └── [presentation: max:5]
 │         ├── best: (scalar-group-by G2 G3 cols=())
 │         └── cost: 1060.04
 ├── G2: (scan abc,cols=(2))
 │    ├── [ordering: -2]
 │    │    ├── best: (sort G2)
 │    │    └── cost: 1269.35
 │    └── []
 │         ├── best: (scan abc,cols=(2))
 │         └── cost: 1050.02
 ├── G3: (aggregations G6)
 ├── G4: (limit G7 G8 ordering=-2)
 │    └── []
 │         ├── best: (limit G7="[ordering: -2]" G8 ordering=-2)
 │         └── cost: 1276.90
 ├── G5: (aggregations G9)
 ├── G6: (max G10)
 ├── G7: (select G2 G11)
 │    ├── [ordering: -2]
 │    │    ├── best: (sort G7)
 │    │    └── cost: 1276.88
 │    └── []
 │         ├── best: (select G2 G11)
 │         └── cost: 1060.03
 ├── G8: (const 1)
 ├── G9: (const-agg G10)
 ├── G10: (variable b)
 ├── G11: (filters G12)
 ├── G12: (is-not G10 G13)
 └── G13: (null)

# --------------------------------------------------
# ReplaceMaxWithLimit
# --------------------------------------------------

opt
SELECT max(a) FROM abc
----
scalar-group-by
 ├── columns: max:5(string)
 ├── cardinality: [1 - 1]
 ├── key: ()
 ├── fd: ()-->(5)
 ├── scan abc,rev
 │    ├── columns: a:1(string!null)
 │    ├── limit: 1(rev)
 │    ├── key: ()
 │    └── fd: ()-->(1)
 └── aggregations
      └── const-agg [type=string, outer=(1)]
           └── variable: a [type=string]

# Verify the rule still fires even if DISTINCT is used.
opt
SELECT max(DISTINCT a) FROM abc
----
scalar-group-by
 ├── columns: max:5(string)
 ├── cardinality: [1 - 1]
 ├── key: ()
 ├── fd: ()-->(5)
 ├── scan abc,rev
 │    ├── columns: a:1(string!null)
 │    ├── limit: 1(rev)
 │    ├── key: ()
 │    └── fd: ()-->(1)
 └── aggregations
      └── const-agg [type=string, outer=(1)]
           └── variable: a [type=string]

opt
SELECT max(b) FROM abc
----
scalar-group-by
 ├── columns: max:5(float)
 ├── cardinality: [1 - 1]
 ├── key: ()
 ├── fd: ()-->(5)
 ├── scan abc
 │    └── columns: b:2(float)
 └── aggregations
      └── max [type=float, outer=(2)]
           └── variable: b [type=float]

memo
SELECT max(b) FROM abc
----
memo (optimized, ~5KB, required=[presentation: max:5])
 ├── G1: (scalar-group-by G2 G3 cols=()) (scalar-group-by G4 G5 cols=())
 │    └── [presentation: max:5]
 │         ├── best: (scalar-group-by G2 G3 cols=())
 │         └── cost: 1060.04
 ├── G2: (scan abc,cols=(2))
 │    ├── [ordering: -2]
 │    │    ├── best: (sort G2)
 │    │    └── cost: 1269.35
 │    └── []
 │         ├── best: (scan abc,cols=(2))
 │         └── cost: 1050.02
 ├── G3: (aggregations G6)
 ├── G4: (limit G7 G8 ordering=-2)
 │    └── []
 │         ├── best: (limit G7="[ordering: -2]" G8 ordering=-2)
 │         └── cost: 1276.90
 ├── G5: (aggregations G9)
 ├── G6: (max G10)
 ├── G7: (select G2 G11)
 │    ├── [ordering: -2]
 │    │    ├── best: (sort G7)
 │    │    └── cost: 1276.88
 │    └── []
 │         ├── best: (select G2 G11)
 │         └── cost: 1060.03
 ├── G8: (const 1)
 ├── G9: (const-agg G10)
 ├── G10: (variable b)
 ├── G11: (filters G12)
 ├── G12: (is-not G10 G13)
 └── G13: (null)

# --------------------------------------------------
# GenerateStreamingGroupBy
# --------------------------------------------------

# All index orderings can be used.
memo
SELECT array_agg(w) FROM (SELECT * FROM kuvw ORDER BY w) GROUP BY u,v
----
memo (optimized, ~5KB, required=[presentation: array_agg:5])
 ├── G1: (project G2 G3 array_agg)
 │    └── [presentation: array_agg:5]
 │         ├── best: (project G2 G3 array_agg)
 │         └── cost: 1120.04
 ├── G2: (group-by G4 G5 cols=(2,3),ordering=+4 opt(2,3)) (group-by G4 G5 cols=(2,3),ordering=+2,+3,+4) (group-by G4 G5 cols=(2,3),ordering=+4,+3,+2) (group-by G4 G5 cols=(2,3),ordering=+3,+4)
 │    └── []
 │         ├── best: (group-by G4="[ordering: +2,+3,+4]" G5 cols=(2,3),ordering=+2,+3,+4)
 │         └── cost: 1110.03
 ├── G3: (projections)
 ├── G4: (scan kuvw,cols=(2-4)) (scan kuvw@uvw,cols=(2-4)) (scan kuvw@wvu,cols=(2-4)) (scan kuvw@vw,cols=(2-4)) (scan kuvw@w,cols=(2-4))
 │    ├── [ordering: +2,+3,+4]
 │    │    ├── best: (scan kuvw@uvw,cols=(2-4))
 │    │    └── cost: 1070.02
 │    ├── [ordering: +3,+4]
 │    │    ├── best: (scan kuvw@vw,cols=(2-4))
 │    │    └── cost: 1070.02
 │    ├── [ordering: +4 opt(2,3)]
 │    │    ├── best: (scan kuvw@uvw,cols=(2-4))
 │    │    └── cost: 1070.02
 │    ├── [ordering: +4,+3,+2]
 │    │    ├── best: (scan kuvw@wvu,cols=(2-4))
 │    │    └── cost: 1070.02
 │    └── []
 │         ├── best: (scan kuvw,cols=(2-4))
 │         └── cost: 1070.02
 ├── G5: (aggregations G6)
 ├── G6: (array-agg G7)
 └── G7: (variable w)

# All index orderings can be used (note that +w is redundant with +w,+v+,u).
memo
SELECT sum(w) FROM kuvw GROUP BY u,v,w
----
memo (optimized, ~5KB, required=[presentation: sum:5])
 ├── G1: (project G2 G3 sum)
 │    └── [presentation: sum:5]
 │         ├── best: (project G2 G3 sum)
 │         └── cost: 1130.04
 ├── G2: (group-by G4 G5 cols=(2-4)) (group-by G4 G5 cols=(2-4),ordering=+2,+3,+4) (group-by G4 G5 cols=(2-4),ordering=+4,+3,+2) (group-by G4 G5 cols=(2-4),ordering=+3,+4)
 │    └── []
 │         ├── best: (group-by G4="[ordering: +2,+3,+4]" G5 cols=(2-4),ordering=+2,+3,+4)
 │         └── cost: 1120.03
 ├── G3: (projections)
 ├── G4: (scan kuvw,cols=(2-4)) (scan kuvw@uvw,cols=(2-4)) (scan kuvw@wvu,cols=(2-4)) (scan kuvw@vw,cols=(2-4)) (scan kuvw@w,cols=(2-4))
 │    ├── [ordering: +2,+3,+4]
 │    │    ├── best: (scan kuvw@uvw,cols=(2-4))
 │    │    └── cost: 1070.02
 │    ├── [ordering: +3,+4]
 │    │    ├── best: (scan kuvw@vw,cols=(2-4))
 │    │    └── cost: 1070.02
 │    ├── [ordering: +4,+3,+2]
 │    │    ├── best: (scan kuvw@wvu,cols=(2-4))
 │    │    └── cost: 1070.02
 │    └── []
 │         ├── best: (scan kuvw,cols=(2-4))
 │         └── cost: 1070.02
 ├── G5: (aggregations G6)
 ├── G6: (sum G7)
 └── G7: (variable w)

# Only index ordering +v,+w can be used (as +v).
memo
SELECT sum(w) FROM kuvw GROUP BY v
----
memo (optimized, ~5KB, required=[presentation: sum:5])
 ├── G1: (project G2 G3 sum)
 │    └── [presentation: sum:5]
 │         ├── best: (project G2 G3 sum)
 │         └── cost: 1082.04
 ├── G2: (group-by G4 G5 cols=(3)) (group-by G4 G5 cols=(3),ordering=+3)
 │    └── []
 │         ├── best: (group-by G4="[ordering: +3]" G5 cols=(3),ordering=+3)
 │         └── cost: 1081.03
 ├── G3: (projections)
 ├── G4: (scan kuvw,cols=(3,4)) (scan kuvw@uvw,cols=(3,4)) (scan kuvw@wvu,cols=(3,4)) (scan kuvw@vw,cols=(3,4)) (scan kuvw@w,cols=(3,4))
 │    ├── [ordering: +3]
 │    │    ├── best: (scan kuvw@vw,cols=(3,4))
 │    │    └── cost: 1060.02
 │    └── []
 │         ├── best: (scan kuvw,cols=(3,4))
 │         └── cost: 1060.02
 ├── G5: (aggregations G6)
 ├── G6: (sum G7)
 └── G7: (variable w)

# Only ordering +u,+v,+w can be used.
memo
SELECT array_agg(w) FROM (SELECT * FROM kuvw ORDER BY u,w) GROUP BY v
----
memo (optimized, ~5KB, required=[presentation: array_agg:5])
 ├── G1: (project G2 G3 array_agg)
 │    └── [presentation: array_agg:5]
 │         ├── best: (project G2 G3 array_agg)
 │         └── cost: 1102.04
 ├── G2: (group-by G4 G5 cols=(3),ordering=+2,+4 opt(3)) (group-by G4 G5 cols=(3),ordering=+2,+3,+4)
 │    └── []
 │         ├── best: (group-by G4="[ordering: +2,+4 opt(3)]" G5 cols=(3),ordering=+2,+4 opt(3))
 │         └── cost: 1101.03
 ├── G3: (projections)
 ├── G4: (scan kuvw,cols=(2-4)) (scan kuvw@uvw,cols=(2-4)) (scan kuvw@wvu,cols=(2-4)) (scan kuvw@vw,cols=(2-4)) (scan kuvw@w,cols=(2-4))
 │    ├── [ordering: +2,+3,+4]
 │    │    ├── best: (scan kuvw@uvw,cols=(2-4))
 │    │    └── cost: 1070.02
 │    ├── [ordering: +2,+4 opt(3)]
 │    │    ├── best: (scan kuvw@uvw,cols=(2-4))
 │    │    └── cost: 1070.02
 │    └── []
 │         ├── best: (scan kuvw,cols=(2-4))
 │         └── cost: 1070.02
 ├── G5: (aggregations G6)
 ├── G6: (array-agg G7)
 └── G7: (variable w)

# Verify the orderings are simplified.
memo
SELECT array_agg(k) FROM (SELECT * FROM kuvw WHERE u=v ORDER BY u) GROUP BY w
----
memo (optimized, ~9KB, required=[presentation: array_agg:5])
 ├── G1: (project G2 G3 array_agg)
 │    └── [presentation: array_agg:5]
 │         ├── best: (project G2 G3 array_agg)
 │         └── cost: 1079.63
 ├── G2: (group-by G4 G5 cols=(4),ordering=+(2|3) opt(4)) (group-by G4 G5 cols=(4),ordering=+(2|3)) (group-by G4 G5 cols=(4),ordering=+4,+(2|3)) (group-by G4 G5 cols=(4),ordering=+(2|3),+4)
 │    └── []
 │         ├── best: (group-by G4="[ordering: +(2|3) opt(4)]" G5 cols=(4),ordering=+(2|3) opt(4))
 │         └── cost: 1079.53
 ├── G3: (projections)
 ├── G4: (select G6 G7) (select G8 G7) (select G9 G7)
 │    ├── [ordering: +(2|3) opt(4)]
 │    │    ├── best: (select G8="[ordering: +2 opt(4)]" G7)
 │    │    └── cost: 1079.12
 │    ├── [ordering: +(2|3),+4]
 │    │    ├── best: (sort G4)
 │    │    └── cost: 1080.04
 │    ├── [ordering: +(2|3)]
 │    │    ├── best: (select G8="[ordering: +2]" G7)
 │    │    └── cost: 1079.12
 │    ├── [ordering: +4,+(2|3)]
 │    │    ├── best: (sort G4)
 │    │    └── cost: 1080.04
 │    └── []
 │         ├── best: (select G8 G7)
 │         └── cost: 1079.12
 ├── G5: (aggregations G10)
 ├── G6: (scan kuvw) (scan kuvw@uvw) (scan kuvw@wvu) (scan kuvw@vw) (scan kuvw@w)
 │    ├── [ordering: +2 opt(4)]
 │    │    ├── best: (scan kuvw@uvw)
 │    │    └── cost: 1080.02
 │    ├── [ordering: +2,+4]
 │    │    ├── best: (sort G6)
 │    │    └── cost: 1310.31
 │    ├── [ordering: +2]
 │    │    ├── best: (scan kuvw@uvw)
 │    │    └── cost: 1080.02
 │    ├── [ordering: +4,+2]
 │    │    ├── best: (sort G6)
 │    │    └── cost: 1310.31
 │    └── []
 │         ├── best: (scan kuvw)
 │         └── cost: 1080.02
 ├── G7: (filters G11)
 ├── G8: (scan kuvw@uvw,constrained)
 │    ├── [ordering: +2 opt(4)]
 │    │    ├── best: (scan kuvw@uvw,constrained)
 │    │    └── cost: 1069.21
 │    ├── [ordering: +2,+4]
 │    │    ├── best: (sort G8)
 │    │    └── cost: 1296.90
 │    ├── [ordering: +2]
 │    │    ├── best: (scan kuvw@uvw,constrained)
 │    │    └── cost: 1069.21
 │    ├── [ordering: +4,+2]
 │    │    ├── best: (sort G8)
 │    │    └── cost: 1296.90
 │    └── []
 │         ├── best: (scan kuvw@uvw,constrained)
 │         └── cost: 1069.21
 ├── G9: (scan kuvw@vw,constrained)
 │    ├── [ordering: +2 opt(4)]
 │    │    ├── best: (sort G9)
 │    │    └── cost: 1286.06
 │    ├── [ordering: +2,+4]
 │    │    ├── best: (sort G9)
 │    │    └── cost: 1296.90
 │    ├── [ordering: +2]
 │    │    ├── best: (sort G9)
 │    │    └── cost: 1286.06
 │    ├── [ordering: +4,+2]
 │    │    ├── best: (sort G9)
 │    │    └── cost: 1296.90
 │    └── []
 │         ├── best: (scan kuvw@vw,constrained)
 │         └── cost: 1069.21
 ├── G10: (array-agg G12)
 ├── G11: (eq G13 G14)
 ├── G12: (variable k)
 ├── G13: (variable u)
 └── G14: (variable v)

memo
SELECT sum(k) FROM (SELECT * FROM kuvw WHERE u=v) GROUP BY u,w
----
memo (optimized, ~8KB, required=[presentation: sum:5])
 ├── G1: (project G2 G3 sum)
 │    └── [presentation: sum:5]
 │         ├── best: (project G2 G3 sum)
 │         └── cost: 1079.69
 ├── G2: (group-by G4 G5 cols=(2,4)) (group-by G4 G5 cols=(2,4),ordering=+(2|3)) (group-by G4 G5 cols=(2,4),ordering=+4)
 │    └── []
 │         ├── best: (group-by G4="[ordering: +(2|3)]" G5 cols=(2,4),ordering=+(2|3))
 │         └── cost: 1079.58
 ├── G3: (projections)
 ├── G4: (select G6 G7) (select G8 G7) (select G9 G7)
 │    ├── [ordering: +(2|3)]
 │    │    ├── best: (select G8="[ordering: +2]" G7)
 │    │    └── cost: 1079.12
 │    ├── [ordering: +4]
 │    │    ├── best: (sort G4)
 │    │    └── cost: 1079.99
 │    └── []
 │         ├── best: (select G8 G7)
 │         └── cost: 1079.12
 ├── G5: (aggregations G10)
 ├── G6: (scan kuvw) (scan kuvw@uvw) (scan kuvw@wvu) (scan kuvw@vw) (scan kuvw@w)
 │    ├── [ordering: +2]
 │    │    ├── best: (scan kuvw@uvw)
 │    │    └── cost: 1080.02
 │    ├── [ordering: +4]
 │    │    ├── best: (scan kuvw@wvu)
 │    │    └── cost: 1080.02
 │    └── []
 │         ├── best: (scan kuvw)
 │         └── cost: 1080.02
 ├── G7: (filters G11)
 ├── G8: (scan kuvw@uvw,constrained)
 │    ├── [ordering: +2]
 │    │    ├── best: (scan kuvw@uvw,constrained)
 │    │    └── cost: 1069.21
 │    ├── [ordering: +4]
 │    │    ├── best: (sort G8)
 │    │    └── cost: 1286.06
 │    └── []
 │         ├── best: (scan kuvw@uvw,constrained)
 │         └── cost: 1069.21
 ├── G9: (scan kuvw@vw,constrained)
 │    ├── [ordering: +2]
 │    │    ├── best: (sort G9)
 │    │    └── cost: 1286.06
 │    ├── [ordering: +4]
 │    │    ├── best: (sort G9)
 │    │    └── cost: 1286.06
 │    └── []
 │         ├── best: (scan kuvw@vw,constrained)
 │         └── cost: 1069.21
 ├── G10: (sum G12)
 ├── G11: (eq G13 G14)
 ├── G12: (variable k)
 ├── G13: (variable u)
 └── G14: (variable v)

# Ensure that we don't incorrectly use orderings that don't match the direction.
memo
SELECT array_agg(w) FROM (SELECT * FROM kuvw ORDER BY w DESC) GROUP BY u,v
----
memo (optimized, ~4KB, required=[presentation: array_agg:5])
 ├── G1: (project G2 G3 array_agg)
 │    └── [presentation: array_agg:5]
 │         ├── best: (project G2 G3 array_agg)
 │         └── cost: 1229.70
 ├── G2: (group-by G4 G5 cols=(2,3),ordering=-4 opt(2,3))
 │    └── []
 │         ├── best: (group-by G4="[ordering: -4 opt(2,3)]" G5 cols=(2,3),ordering=-4 opt(2,3))
 │         └── cost: 1219.69
 ├── G3: (projections)
 ├── G4: (scan kuvw,cols=(2-4)) (scan kuvw@uvw,cols=(2-4)) (scan kuvw@wvu,cols=(2-4)) (scan kuvw@vw,cols=(2-4)) (scan kuvw@w,cols=(2-4))
 │    ├── [ordering: -4 opt(2,3)]
 │    │    ├── best: (scan kuvw@uvw,rev,cols=(2-4))
 │    │    └── cost: 1169.68
 │    └── []
 │         ├── best: (scan kuvw,cols=(2-4))
 │         └── cost: 1070.02
 ├── G5: (aggregations G6)
 ├── G6: (array-agg G7)
 └── G7: (variable w)


# All orderings can be used (note that +w is redundant with +w,+v,+u).
memo
SELECT DISTINCT u, v, w FROM kuvw
----
memo (optimized, ~4KB, required=[presentation: u:2,v:3,w:4])
 ├── G1: (distinct-on G2 G3 cols=(2-4)) (distinct-on G2 G3 cols=(2-4),ordering=+2,+3,+4) (distinct-on G2 G3 cols=(2-4),ordering=+4,+3,+2) (distinct-on G2 G3 cols=(2-4),ordering=+3,+4)
 │    └── [presentation: u:2,v:3,w:4]
 │         ├── best: (distinct-on G2="[ordering: +2,+3,+4]" G3 cols=(2-4),ordering=+2,+3,+4)
 │         └── cost: 1110.03
 ├── G2: (scan kuvw,cols=(2-4)) (scan kuvw@uvw,cols=(2-4)) (scan kuvw@wvu,cols=(2-4)) (scan kuvw@vw,cols=(2-4)) (scan kuvw@w,cols=(2-4))
 │    ├── [ordering: +2,+3,+4]
 │    │    ├── best: (scan kuvw@uvw,cols=(2-4))
 │    │    └── cost: 1070.02
 │    ├── [ordering: +3,+4]
 │    │    ├── best: (scan kuvw@vw,cols=(2-4))
 │    │    └── cost: 1070.02
 │    ├── [ordering: +4,+3,+2]
 │    │    ├── best: (scan kuvw@wvu,cols=(2-4))
 │    │    └── cost: 1070.02
 │    └── []
 │         ├── best: (scan kuvw,cols=(2-4))
 │         └── cost: 1070.02
 └── G3: (aggregations)

# Orderings +u,+v and +v can be used.
memo
SELECT DISTINCT ON (u, v) u, v, w FROM kuvw
----
memo (optimized, ~4KB, required=[presentation: u:2,v:3,w:4])
 ├── G1: (distinct-on G2 G3 cols=(2,3)) (distinct-on G2 G3 cols=(2,3),ordering=+2,+3) (distinct-on G2 G3 cols=(2,3),ordering=+3)
 │    └── [presentation: u:2,v:3,w:4]
 │         ├── best: (distinct-on G2="[ordering: +2,+3]" G3 cols=(2,3),ordering=+2,+3)
 │         └── cost: 1110.03
 ├── G2: (scan kuvw,cols=(2-4)) (scan kuvw@uvw,cols=(2-4)) (scan kuvw@wvu,cols=(2-4)) (scan kuvw@vw,cols=(2-4)) (scan kuvw@w,cols=(2-4))
 │    ├── [ordering: +2,+3]
 │    │    ├── best: (scan kuvw@uvw,cols=(2-4))
 │    │    └── cost: 1070.02
 │    ├── [ordering: +3]
 │    │    ├── best: (scan kuvw@vw,cols=(2-4))
 │    │    └── cost: 1070.02
 │    └── []
 │         ├── best: (scan kuvw,cols=(2-4))
 │         └── cost: 1070.02
 ├── G3: (aggregations G4)
 ├── G4: (first-agg G5)
 └── G5: (variable w)

# Only ordering +u can be used.
memo
SELECT DISTINCT ON (u) u, v, w FROM kuvw
----
memo (optimized, ~4KB, required=[presentation: u:2,v:3,w:4])
 ├── G1: (distinct-on G2 G3 cols=(2)) (distinct-on G2 G3 cols=(2),ordering=+2)
 │    └── [presentation: u:2,v:3,w:4]
 │         ├── best: (distinct-on G2="[ordering: +2]" G3 cols=(2),ordering=+2)
 │         └── cost: 1101.03
 ├── G2: (scan kuvw,cols=(2-4)) (scan kuvw@uvw,cols=(2-4)) (scan kuvw@wvu,cols=(2-4)) (scan kuvw@vw,cols=(2-4)) (scan kuvw@w,cols=(2-4))
 │    ├── [ordering: +2]
 │    │    ├── best: (scan kuvw@uvw,cols=(2-4))
 │    │    └── cost: 1070.02
 │    └── []
 │         ├── best: (scan kuvw,cols=(2-4))
 │         └── cost: 1070.02
 ├── G3: (aggregations G4 G5)
 ├── G4: (first-agg G6)
 ├── G5: (first-agg G7)
 ├── G6: (variable v)
 └── G7: (variable w)

# Only ordering +v can be used.
memo
SELECT DISTINCT ON (v) u, v, w FROM kuvw
----
memo (optimized, ~4KB, required=[presentation: u:2,v:3,w:4])
 ├── G1: (distinct-on G2 G3 cols=(3)) (distinct-on G2 G3 cols=(3),ordering=+3)
 │    └── [presentation: u:2,v:3,w:4]
 │         ├── best: (distinct-on G2="[ordering: +3]" G3 cols=(3),ordering=+3)
 │         └── cost: 1101.03
 ├── G2: (scan kuvw,cols=(2-4)) (scan kuvw@uvw,cols=(2-4)) (scan kuvw@wvu,cols=(2-4)) (scan kuvw@vw,cols=(2-4)) (scan kuvw@w,cols=(2-4))
 │    ├── [ordering: +3]
 │    │    ├── best: (scan kuvw@vw,cols=(2-4))
 │    │    └── cost: 1070.02
 │    └── []
 │         ├── best: (scan kuvw,cols=(2-4))
 │         └── cost: 1070.02
 ├── G3: (aggregations G4 G5)
 ├── G4: (first-agg G6)
 ├── G5: (first-agg G7)
 ├── G6: (variable u)
 └── G7: (variable w)

# Only ordering +w can be used.
memo
SELECT DISTINCT ON (w) u, v, w FROM kuvw
----
memo (optimized, ~4KB, required=[presentation: u:2,v:3,w:4])
 ├── G1: (distinct-on G2 G3 cols=(4)) (distinct-on G2 G3 cols=(4),ordering=+4)
 │    └── [presentation: u:2,v:3,w:4]
 │         ├── best: (distinct-on G2="[ordering: +4]" G3 cols=(4),ordering=+4)
 │         └── cost: 1101.03
 ├── G2: (scan kuvw,cols=(2-4)) (scan kuvw@uvw,cols=(2-4)) (scan kuvw@wvu,cols=(2-4)) (scan kuvw@vw,cols=(2-4)) (scan kuvw@w,cols=(2-4))
 │    ├── [ordering: +4]
 │    │    ├── best: (scan kuvw@wvu,cols=(2-4))
 │    │    └── cost: 1070.02
 │    └── []
 │         ├── best: (scan kuvw,cols=(2-4))
 │         └── cost: 1070.02
 ├── G3: (aggregations G4 G5)
 ├── G4: (first-agg G6)
 ├── G5: (first-agg G7)
 ├── G6: (variable u)
 └── G7: (variable v)

# Only ordering +u can be used.
memo
SELECT DISTINCT ON (u) u, v, w FROM kuvw ORDER BY u, w
----
memo (optimized, ~4KB, required=[presentation: u:2,v:3,w:4] [ordering: +2])
 ├── G1: (distinct-on G2 G3 cols=(2),ordering=+4 opt(2)) (distinct-on G2 G3 cols=(2),ordering=+4)
 │    ├── [presentation: u:2,v:3,w:4] [ordering: +2]
 │    │    ├── best: (sort G1)
 │    │    └── cost: 1126.33
 │    └── []
 │         ├── best: (distinct-on G2="[ordering: +4 opt(2)]" G3 cols=(2),ordering=+4 opt(2))
 │         └── cost: 1111.03
 ├── G2: (scan kuvw,cols=(2-4)) (scan kuvw@uvw,cols=(2-4)) (scan kuvw@wvu,cols=(2-4)) (scan kuvw@vw,cols=(2-4)) (scan kuvw@w,cols=(2-4))
 │    ├── [ordering: +2,+4]
 │    │    ├── best: (sort G2)
 │    │    └── cost: 1300.31
 │    ├── [ordering: +4 opt(2)]
 │    │    ├── best: (scan kuvw@wvu,cols=(2-4))
 │    │    └── cost: 1070.02
 │    ├── [ordering: +4]
 │    │    ├── best: (scan kuvw@wvu,cols=(2-4))
 │    │    └── cost: 1070.02
 │    └── []
 │         ├── best: (scan kuvw,cols=(2-4))
 │         └── cost: 1070.02
 ├── G3: (aggregations G4 G5)
 ├── G4: (first-agg G6)
 ├── G5: (first-agg G7)
 ├── G6: (variable v)
 └── G7: (variable w)

# Only ordering +u,+v,+w can be used.
memo
SELECT DISTINCT ON (u) u, v, w FROM kuvw ORDER BY u, v, w
----
memo (optimized, ~4KB, required=[presentation: u:2,v:3,w:4] [ordering: +2])
 ├── G1: (distinct-on G2 G3 cols=(2),ordering=+3,+4 opt(2)) (distinct-on G2 G3 cols=(2),ordering=+2,+3,+4) (distinct-on G2 G3 cols=(2),ordering=+3,+4)
 │    ├── [presentation: u:2,v:3,w:4] [ordering: +2]
 │    │    ├── best: (distinct-on G2="[ordering: +2,+3,+4]" G3 cols=(2),ordering=+3,+4 opt(2))
 │    │    └── cost: 1101.03
 │    └── []
 │         ├── best: (distinct-on G2="[ordering: +2,+3,+4]" G3 cols=(2),ordering=+2,+3,+4)
 │         └── cost: 1101.03
 ├── G2: (scan kuvw,cols=(2-4)) (scan kuvw@uvw,cols=(2-4)) (scan kuvw@wvu,cols=(2-4)) (scan kuvw@vw,cols=(2-4)) (scan kuvw@w,cols=(2-4))
 │    ├── [ordering: +2,+3,+4]
 │    │    ├── best: (scan kuvw@uvw,cols=(2-4))
 │    │    └── cost: 1070.02
 │    ├── [ordering: +3,+4 opt(2)]
 │    │    ├── best: (scan kuvw@uvw,cols=(2-4))
 │    │    └── cost: 1070.02
 │    ├── [ordering: +3,+4]
 │    │    ├── best: (scan kuvw@vw,cols=(2-4))
 │    │    └── cost: 1070.02
 │    └── []
 │         ├── best: (scan kuvw,cols=(2-4))
 │         └── cost: 1070.02
 ├── G3: (aggregations G4 G5)
 ├── G4: (first-agg G6)
 ├── G5: (first-agg G7)
 ├── G6: (variable v)
 └── G7: (variable w)

# Ensure that we don't incorrectly use orderings that don't match the direction.
memo
SELECT DISTINCT ON (w, u) u, v, w FROM kuvw ORDER BY w, u, v DESC
----
memo (optimized, ~3KB, required=[presentation: u:2,v:3,w:4] [ordering: +4,+2])
 ├── G1: (distinct-on G2 G3 cols=(2,4),ordering=-3 opt(2,4))
 │    ├── [presentation: u:2,v:3,w:4] [ordering: +4,+2]
 │    │    ├── best: (distinct-on G2="[ordering: +4,+2,-3]" G3 cols=(2,4),ordering=-3 opt(2,4))
 │    │    └── cost: 1341.42
 │    └── []
 │         ├── best: (distinct-on G2="[ordering: -3 opt(2,4)]" G3 cols=(2,4),ordering=-3 opt(2,4))
 │         └── cost: 1219.69
 ├── G2: (scan kuvw,cols=(2-4)) (scan kuvw@uvw,cols=(2-4)) (scan kuvw@wvu,cols=(2-4)) (scan kuvw@vw,cols=(2-4)) (scan kuvw@w,cols=(2-4))
 │    ├── [ordering: +4,+2,-3]
 │    │    ├── best: (sort G2)
 │    │    └── cost: 1301.41
 │    ├── [ordering: -3 opt(2,4)]
 │    │    ├── best: (scan kuvw@uvw,rev,cols=(2-4))
 │    │    └── cost: 1169.68
 │    └── []
 │         ├── best: (scan kuvw,cols=(2-4))
 │         └── cost: 1070.02
 ├── G3: (aggregations G4)
 ├── G4: (first-agg G5)
 └── G5: (variable v)

memo
SELECT DISTINCT ON (w) u, v, w FROM kuvw ORDER BY w, u DESC, v
----
memo (optimized, ~4KB, required=[presentation: u:2,v:3,w:4] [ordering: +4])
 ├── G1: (distinct-on G2 G3 cols=(4),ordering=-2,+3 opt(4))
 │    ├── [presentation: u:2,v:3,w:4] [ordering: +4]
 │    │    ├── best: (distinct-on G2="[ordering: +4,-2,+3]" G3 cols=(4),ordering=-2,+3 opt(4))
 │    │    └── cost: 1332.42
 │    └── []
 │         ├── best: (distinct-on G2="[ordering: -2,+3 opt(4)]" G3 cols=(4),ordering=-2,+3 opt(4))
 │         └── cost: 1341.32
 ├── G2: (scan kuvw,cols=(2-4)) (scan kuvw@uvw,cols=(2-4)) (scan kuvw@wvu,cols=(2-4)) (scan kuvw@vw,cols=(2-4)) (scan kuvw@w,cols=(2-4))
 │    ├── [ordering: +4,-2,+3]
 │    │    ├── best: (sort G2)
 │    │    └── cost: 1301.41
 │    ├── [ordering: -2,+3 opt(4)]
 │    │    ├── best: (sort G2)
 │    │    └── cost: 1300.31
 │    └── []
 │         ├── best: (scan kuvw,cols=(2-4))
 │         └── cost: 1070.02
 ├── G3: (aggregations G4 G5)
 ├── G4: (first-agg G6)
 ├── G5: (first-agg G7)
 ├── G6: (variable u)
 └── G7: (variable v)

memo
SELECT DISTINCT ON (w) u, v, w FROM kuvw ORDER BY w DESC, u DESC, v
----
memo (optimized, ~4KB, required=[presentation: u:2,v:3,w:4] [ordering: -4])
 ├── G1: (distinct-on G2 G3 cols=(4),ordering=-2,+3 opt(4))
 │    ├── [presentation: u:2,v:3,w:4] [ordering: -4]
 │    │    ├── best: (distinct-on G2="[ordering: -4,-2,+3]" G3 cols=(4),ordering=-2,+3 opt(4))
 │    │    └── cost: 1332.42
 │    └── []
 │         ├── best: (distinct-on G2="[ordering: -2,+3 opt(4)]" G3 cols=(4),ordering=-2,+3 opt(4))
 │         └── cost: 1341.32
 ├── G2: (scan kuvw,cols=(2-4)) (scan kuvw@uvw,cols=(2-4)) (scan kuvw@wvu,cols=(2-4)) (scan kuvw@vw,cols=(2-4)) (scan kuvw@w,cols=(2-4))
 │    ├── [ordering: -2,+3 opt(4)]
 │    │    ├── best: (sort G2)
 │    │    └── cost: 1300.31
 │    ├── [ordering: -4,-2,+3]
 │    │    ├── best: (sort G2)
 │    │    └── cost: 1301.41
 │    └── []
 │         ├── best: (scan kuvw,cols=(2-4))
 │         └── cost: 1070.02
 ├── G3: (aggregations G4 G5)
 ├── G4: (first-agg G6)
 ├── G5: (first-agg G7)
 ├── G6: (variable u)
 └── G7: (variable v)

memo
SELECT DISTINCT ON (w) u, v, w FROM kuvw ORDER BY w, u, v DESC
----
memo (optimized, ~4KB, required=[presentation: u:2,v:3,w:4] [ordering: +4])
 ├── G1: (distinct-on G2 G3 cols=(4),ordering=+2,-3 opt(4))
 │    ├── [presentation: u:2,v:3,w:4] [ordering: +4]
 │    │    ├── best: (distinct-on G2="[ordering: +4,+2,-3]" G3 cols=(4),ordering=+2,-3 opt(4))
 │    │    └── cost: 1332.42
 │    └── []
 │         ├── best: (distinct-on G2="[ordering: +2,-3 opt(4)]" G3 cols=(4),ordering=+2,-3 opt(4))
 │         └── cost: 1341.32
 ├── G2: (scan kuvw,cols=(2-4)) (scan kuvw@uvw,cols=(2-4)) (scan kuvw@wvu,cols=(2-4)) (scan kuvw@vw,cols=(2-4)) (scan kuvw@w,cols=(2-4))
 │    ├── [ordering: +2,-3 opt(4)]
 │    │    ├── best: (sort G2)
 │    │    └── cost: 1300.31
 │    ├── [ordering: +4,+2,-3]
 │    │    ├── best: (sort G2)
 │    │    └── cost: 1301.41
 │    └── []
 │         ├── best: (scan kuvw,cols=(2-4))
 │         └── cost: 1070.02
 ├── G3: (aggregations G4 G5)
 ├── G4: (first-agg G6)
 ├── G5: (first-agg G7)
 ├── G6: (variable u)
 └── G7: (variable v)
