github.com/cockroachdb/cockroach@v20.2.0-alpha.1+incompatible/pkg/sql/opt/xform/testdata/rules/join_order (about)

     1  exec-ddl
     2  CREATE TABLE bx (
     3    b INT PRIMARY KEY,
     4    x INT
     5  )
     6  ----
     7  
     8  exec-ddl
     9  CREATE TABLE cy (
    10    c INT PRIMARY KEY,
    11    y INT
    12  )
    13  ----
    14  
    15  exec-ddl
    16  CREATE TABLE dz (
    17    d INT PRIMARY KEY,
    18    z INT
    19  )
    20  ----
    21  
    22  exec-ddl
    23  CREATE TABLE abc (
    24    a INT PRIMARY KEY,
    25    b INT,
    26    c INT,
    27    d INT
    28  )
    29  ----
    30  
    31  opt join-limit=3
    32  SELECT * FROM abc, bx, cy WHERE a = 1 AND abc.b = bx.b AND abc.c = cy.c
    33  ----
    34  inner-join (lookup bx)
    35   ├── columns: a:1!null b:2!null c:3!null d:4 b:5!null x:6 c:7!null y:8
    36   ├── key columns: [2] = [5]
    37   ├── lookup columns are key
    38   ├── cardinality: [0 - 1]
    39   ├── key: ()
    40   ├── fd: ()-->(1-8)
    41   ├── inner-join (lookup cy)
    42   │    ├── columns: a:1!null abc.b:2 abc.c:3!null d:4 cy.c:7!null y:8
    43   │    ├── key columns: [3] = [7]
    44   │    ├── lookup columns are key
    45   │    ├── cardinality: [0 - 1]
    46   │    ├── key: ()
    47   │    ├── fd: ()-->(1-4,7,8)
    48   │    ├── scan abc
    49   │    │    ├── columns: a:1!null abc.b:2 abc.c:3 d:4
    50   │    │    ├── constraint: /1: [/1 - /1]
    51   │    │    ├── cardinality: [0 - 1]
    52   │    │    ├── key: ()
    53   │    │    └── fd: ()-->(1-4)
    54   │    └── filters (true)
    55   └── filters (true)
    56  
    57  opt join-limit=3
    58  SELECT * FROM bx, abc, cy WHERE a = 1 AND abc.b = bx.b AND abc.c = cy.c
    59  ----
    60  inner-join (lookup bx)
    61   ├── columns: b:1!null x:2 a:3!null b:4!null c:5!null d:6 c:7!null y:8
    62   ├── key columns: [4] = [1]
    63   ├── lookup columns are key
    64   ├── cardinality: [0 - 1]
    65   ├── key: ()
    66   ├── fd: ()-->(1-8)
    67   ├── inner-join (lookup cy)
    68   │    ├── columns: a:3!null abc.b:4 abc.c:5!null d:6 cy.c:7!null y:8
    69   │    ├── key columns: [5] = [7]
    70   │    ├── lookup columns are key
    71   │    ├── cardinality: [0 - 1]
    72   │    ├── key: ()
    73   │    ├── fd: ()-->(3-8)
    74   │    ├── scan abc
    75   │    │    ├── columns: a:3!null abc.b:4 abc.c:5 d:6
    76   │    │    ├── constraint: /3: [/1 - /1]
    77   │    │    ├── cardinality: [0 - 1]
    78   │    │    ├── key: ()
    79   │    │    └── fd: ()-->(3-6)
    80   │    └── filters (true)
    81   └── filters (true)
    82  
    83  opt join-limit=3
    84  SELECT * FROM bx, cy, abc WHERE a = 1 AND abc.b = bx.b AND abc.c = cy.c
    85  ----
    86  inner-join (lookup bx)
    87   ├── columns: b:1!null x:2 c:3!null y:4 a:5!null b:6!null c:7!null d:8
    88   ├── key columns: [6] = [1]
    89   ├── lookup columns are key
    90   ├── cardinality: [0 - 1]
    91   ├── key: ()
    92   ├── fd: ()-->(1-8)
    93   ├── inner-join (lookup cy)
    94   │    ├── columns: cy.c:3!null y:4 a:5!null abc.b:6 abc.c:7!null d:8
    95   │    ├── key columns: [7] = [3]
    96   │    ├── lookup columns are key
    97   │    ├── cardinality: [0 - 1]
    98   │    ├── key: ()
    99   │    ├── fd: ()-->(3-8)
   100   │    ├── scan abc
   101   │    │    ├── columns: a:5!null abc.b:6 abc.c:7 d:8
   102   │    │    ├── constraint: /5: [/1 - /1]
   103   │    │    ├── cardinality: [0 - 1]
   104   │    │    ├── key: ()
   105   │    │    └── fd: ()-->(5-8)
   106   │    └── filters (true)
   107   └── filters (true)
   108  
   109  opt join-limit=2 expect-not=AssociateJoin
   110  SELECT * FROM bx, cy, abc WHERE a = 1 AND abc.b = bx.b AND abc.c = cy.c
   111  ----
   112  inner-join (lookup bx)
   113   ├── columns: b:1!null x:2 c:3!null y:4 a:5!null b:6!null c:7!null d:8
   114   ├── key columns: [6] = [1]
   115   ├── lookup columns are key
   116   ├── cardinality: [0 - 1]
   117   ├── key: ()
   118   ├── fd: ()-->(1-8)
   119   ├── inner-join (lookup cy)
   120   │    ├── columns: cy.c:3!null y:4 a:5!null abc.b:6 abc.c:7!null d:8
   121   │    ├── key columns: [7] = [3]
   122   │    ├── lookup columns are key
   123   │    ├── cardinality: [0 - 1]
   124   │    ├── key: ()
   125   │    ├── fd: ()-->(3-8)
   126   │    ├── scan abc
   127   │    │    ├── columns: a:5!null abc.b:6 abc.c:7 d:8
   128   │    │    ├── constraint: /5: [/1 - /1]
   129   │    │    ├── cardinality: [0 - 1]
   130   │    │    ├── key: ()
   131   │    │    └── fd: ()-->(5-8)
   132   │    └── filters (true)
   133   └── filters (true)
   134  
   135  memo join-limit=3
   136  SELECT * FROM bx, cy, abc WHERE a = 1 AND abc.b = bx.b AND abc.c = cy.c
   137  ----
   138  memo (optimized, ~33KB, required=[presentation: b:1,x:2,c:3,y:4,a:5,b:6,c:7,d:8])
   139   ├── G1: (inner-join G2 G3 G4) (inner-join G3 G2 G4) (merge-join G2 G3 G5 inner-join,+1,+6) (lookup-join G3 G5 bx,keyCols=[6],outCols=(1-8)) (inner-join G6 G7 G8) (inner-join G9 G10 G11) (inner-join G7 G6 G8) (merge-join G6 G7 G5 inner-join,+3,+7) (inner-join G10 G9 G11) (lookup-join G7 G5 cy,keyCols=[7],outCols=(1-8)) (lookup-join G12 G11 abc,keyCols=[11],outCols=(1-8))
   140   │    └── [presentation: b:1,x:2,c:3,y:4,a:5,b:6,c:7,d:8]
   141   │         ├── best: (lookup-join G3 G5 bx,keyCols=[6],outCols=(1-8))
   142   │         └── cost: 13.11
   143   ├── G2: (scan bx)
   144   │    ├── [ordering: +1]
   145   │    │    ├── best: (scan bx)
   146   │    │    └── cost: 1040.02
   147   │    └── []
   148   │         ├── best: (scan bx)
   149   │         └── cost: 1040.02
   150   ├── G3: (inner-join G6 G9 G8) (inner-join G9 G6 G8) (merge-join G6 G9 G5 inner-join,+3,+7) (lookup-join G13 G8 abc,keyCols=[9],outCols=(3-8)) (lookup-join G9 G5 cy,keyCols=[7],outCols=(3-8))
   151   │    └── []
   152   │         ├── best: (lookup-join G9 G5 cy,keyCols=[7],outCols=(3-8))
   153   │         └── cost: 7.12
   154   ├── G4: (filters G14)
   155   ├── G5: (filters)
   156   ├── G6: (scan cy)
   157   │    ├── [ordering: +3]
   158   │    │    ├── best: (scan cy)
   159   │    │    └── cost: 1040.02
   160   │    └── []
   161   │         ├── best: (scan cy)
   162   │         └── cost: 1040.02
   163   ├── G7: (inner-join G9 G2 G4) (inner-join G2 G9 G4) (lookup-join G9 G5 bx,keyCols=[6],outCols=(1,2,5-8)) (merge-join G2 G9 G5 inner-join,+1,+6) (lookup-join G15 G4 abc,keyCols=[10],outCols=(1,2,5-8))
   164   │    └── []
   165   │         ├── best: (lookup-join G9 G5 bx,keyCols=[6],outCols=(1,2,5-8))
   166   │         └── cost: 7.12
   167   ├── G8: (filters G16)
   168   ├── G9: (select G17 G18) (scan abc,constrained)
   169   │    └── []
   170   │         ├── best: (scan abc,constrained)
   171   │         └── cost: 1.09
   172   ├── G10: (inner-join G6 G2 G5) (inner-join G2 G6 G5)
   173   │    └── []
   174   │         ├── best: (inner-join G6 G2 G5)
   175   │         └── cost: 12110.05
   176   ├── G11: (filters G14 G16)
   177   ├── G12: (project G10 G19 b x c y)
   178   │    └── []
   179   │         ├── best: (project G10 G19 b x c y)
   180   │         └── cost: 32110.06
   181   ├── G13: (project G6 G19 c y)
   182   │    └── []
   183   │         ├── best: (project G6 G19 c y)
   184   │         └── cost: 1060.03
   185   ├── G14: (eq G20 G21)
   186   ├── G15: (project G2 G19 b x)
   187   │    └── []
   188   │         ├── best: (project G2 G19 b x)
   189   │         └── cost: 1060.03
   190   ├── G16: (eq G22 G23)
   191   ├── G17: (scan abc)
   192   │    └── []
   193   │         ├── best: (scan abc)
   194   │         └── cost: 1080.02
   195   ├── G18: (filters G24)
   196   ├── G19: (projections G25)
   197   ├── G20: (variable abc.b)
   198   ├── G21: (variable bx.b)
   199   ├── G22: (variable abc.c)
   200   ├── G23: (variable cy.c)
   201   ├── G24: (eq G26 G25)
   202   ├── G25: (const 1)
   203   └── G26: (variable a)
   204  
   205  opt join-limit=4
   206  SELECT * FROM bx, cy, dz, abc WHERE a = 1
   207  ----
   208  inner-join (cross)
   209   ├── columns: b:1!null x:2 c:3!null y:4 d:5!null z:6 a:7!null b:8 c:9 d:10
   210   ├── key: (1,3,5)
   211   ├── fd: ()-->(7-10), (1)-->(2), (3)-->(4), (5)-->(6)
   212   ├── inner-join (cross)
   213   │    ├── columns: cy.c:3!null y:4 dz.d:5!null z:6 a:7!null abc.b:8 abc.c:9 abc.d:10
   214   │    ├── key: (3,5)
   215   │    ├── fd: ()-->(7-10), (3)-->(4), (5)-->(6)
   216   │    ├── scan cy
   217   │    │    ├── columns: cy.c:3!null y:4
   218   │    │    ├── key: (3)
   219   │    │    └── fd: (3)-->(4)
   220   │    ├── inner-join (cross)
   221   │    │    ├── columns: dz.d:5!null z:6 a:7!null abc.b:8 abc.c:9 abc.d:10
   222   │    │    ├── key: (5)
   223   │    │    ├── fd: ()-->(7-10), (5)-->(6)
   224   │    │    ├── scan dz
   225   │    │    │    ├── columns: dz.d:5!null z:6
   226   │    │    │    ├── key: (5)
   227   │    │    │    └── fd: (5)-->(6)
   228   │    │    ├── scan abc
   229   │    │    │    ├── columns: a:7!null abc.b:8 abc.c:9 abc.d:10
   230   │    │    │    ├── constraint: /7: [/1 - /1]
   231   │    │    │    ├── cardinality: [0 - 1]
   232   │    │    │    ├── key: ()
   233   │    │    │    └── fd: ()-->(7-10)
   234   │    │    └── filters (true)
   235   │    └── filters (true)
   236   ├── scan bx
   237   │    ├── columns: bx.b:1!null x:2
   238   │    ├── key: (1)
   239   │    └── fd: (1)-->(2)
   240   └── filters (true)
   241  
   242  opt join-limit=3 format=show-all
   243  SELECT * FROM abc, bx, cy, dz WHERE a = 1
   244  ----
   245  inner-join (cross)
   246   ├── columns: a:1(int!null) b:2(int) c:3(int) d:4(int) b:5(int!null) x:6(int) c:7(int!null) y:8(int) d:9(int!null) z:10(int)
   247   ├── stats: [rows=1e+09]
   248   ├── cost: 32525668.7
   249   ├── key: (5,7,9)
   250   ├── fd: ()-->(1-4), (5)-->(6), (7)-->(8), (9)-->(10)
   251   ├── prune: (2-10)
   252   ├── interesting orderings: (+7) (+9) (+5) (+1)
   253   ├── multiplicity: left-rows(one-or-zero), right-rows(zero-or-more)
   254   ├── inner-join (cross)
   255   │    ├── columns: t.public.bx.b:5(int!null) t.public.bx.x:6(int) t.public.cy.c:7(int!null) t.public.cy.y:8(int) t.public.dz.d:9(int!null) t.public.dz.z:10(int)
   256   │    ├── stats: [rows=1e+09]
   257   │    ├── cost: 10025667.6
   258   │    ├── key: (5,7,9)
   259   │    ├── fd: (5)-->(6), (7)-->(8), (9)-->(10)
   260   │    ├── prune: (5-10)
   261   │    ├── interesting orderings: (+7) (+9) (+5)
   262   │    ├── join-size: 3
   263   │    ├── inner-join (cross)
   264   │    │    ├── columns: t.public.cy.c:7(int!null) t.public.cy.y:8(int) t.public.dz.d:9(int!null) t.public.dz.z:10(int)
   265   │    │    ├── stats: [rows=1000000]
   266   │    │    ├── cost: 12110.05
   267   │    │    ├── key: (7,9)
   268   │    │    ├── fd: (7)-->(8), (9)-->(10)
   269   │    │    ├── prune: (7-10)
   270   │    │    ├── interesting orderings: (+7) (+9)
   271   │    │    ├── join-size: 2
   272   │    │    ├── scan t.public.cy
   273   │    │    │    ├── columns: t.public.cy.c:7(int!null) t.public.cy.y:8(int)
   274   │    │    │    ├── stats: [rows=1000]
   275   │    │    │    ├── cost: 1040.02
   276   │    │    │    ├── key: (7)
   277   │    │    │    ├── fd: (7)-->(8)
   278   │    │    │    ├── prune: (7,8)
   279   │    │    │    └── interesting orderings: (+7)
   280   │    │    ├── scan t.public.dz
   281   │    │    │    ├── columns: t.public.dz.d:9(int!null) t.public.dz.z:10(int)
   282   │    │    │    ├── stats: [rows=1000]
   283   │    │    │    ├── cost: 1040.02
   284   │    │    │    ├── key: (9)
   285   │    │    │    ├── fd: (9)-->(10)
   286   │    │    │    ├── prune: (9,10)
   287   │    │    │    └── interesting orderings: (+9)
   288   │    │    └── filters (true)
   289   │    ├── scan t.public.bx
   290   │    │    ├── columns: t.public.bx.b:5(int!null) t.public.bx.x:6(int)
   291   │    │    ├── stats: [rows=1000]
   292   │    │    ├── cost: 1040.02
   293   │    │    ├── key: (5)
   294   │    │    ├── fd: (5)-->(6)
   295   │    │    ├── prune: (5,6)
   296   │    │    └── interesting orderings: (+5)
   297   │    └── filters (true)
   298   ├── scan t.public.abc
   299   │    ├── columns: t.public.abc.a:1(int!null) t.public.abc.b:2(int) t.public.abc.c:3(int) t.public.abc.d:4(int)
   300   │    ├── constraint: /1: [/1 - /1]
   301   │    ├── cardinality: [0 - 1]
   302   │    ├── stats: [rows=1, distinct(1)=1, null(1)=0]
   303   │    ├── cost: 1.09
   304   │    ├── key: ()
   305   │    ├── fd: ()-->(1-4)
   306   │    ├── prune: (2-4)
   307   │    └── interesting orderings: (+1)
   308   └── filters (true)
   309  
   310  # Note the difference in memo size for with and without reorder-joins, for only four tables.
   311  # TODO(justin): Find a way to reduce this.
   312  
   313  memo join-limit=1
   314  SELECT * FROM bx, cy, dz, abc WHERE a = 1
   315  ----
   316  memo (optimized, ~13KB, required=[presentation: b:1,x:2,c:3,y:4,d:5,z:6,a:7,b:8,c:9,d:10])
   317   ├── G1: (inner-join G2 G3 G4) (inner-join G3 G2 G4)
   318   │    └── [presentation: b:1,x:2,c:3,y:4,d:5,z:6,a:7,b:8,c:9,d:10]
   319   │         ├── best: (inner-join G3 G2 G4)
   320   │         └── cost: 10025691.20
   321   ├── G2: (scan bx)
   322   │    └── []
   323   │         ├── best: (scan bx)
   324   │         └── cost: 1040.02
   325   ├── G3: (inner-join G5 G6 G4) (inner-join G6 G5 G4)
   326   │    └── []
   327   │         ├── best: (inner-join G5 G6 G4)
   328   │         └── cost: 12133.67
   329   ├── G4: (filters)
   330   ├── G5: (scan cy)
   331   │    └── []
   332   │         ├── best: (scan cy)
   333   │         └── cost: 1040.02
   334   ├── G6: (inner-join G7 G8 G4) (inner-join G8 G7 G4)
   335   │    └── []
   336   │         ├── best: (inner-join G7 G8 G4)
   337   │         └── cost: 1063.64
   338   ├── G7: (scan dz)
   339   │    └── []
   340   │         ├── best: (scan dz)
   341   │         └── cost: 1040.02
   342   ├── G8: (select G9 G10) (scan abc,constrained)
   343   │    └── []
   344   │         ├── best: (scan abc,constrained)
   345   │         └── cost: 1.09
   346   ├── G9: (scan abc)
   347   │    └── []
   348   │         ├── best: (scan abc)
   349   │         └── cost: 1080.02
   350   ├── G10: (filters G11)
   351   ├── G11: (eq G12 G13)
   352   ├── G12: (variable a)
   353   └── G13: (const 1)
   354  
   355  memo join-limit=4
   356  SELECT * FROM bx, cy, dz, abc WHERE a = 1
   357  ----
   358  memo (optimized, ~28KB, required=[presentation: b:1,x:2,c:3,y:4,d:5,z:6,a:7,b:8,c:9,d:10])
   359   ├── G1: (inner-join G2 G3 G4) (inner-join G3 G2 G4) (inner-join G5 G6 G4) (inner-join G7 G8 G4) (inner-join G9 G10 G4) (inner-join G11 G12 G4) (inner-join G13 G14 G4) (inner-join G15 G16 G4) (inner-join G6 G5 G4) (inner-join G8 G7 G4) (inner-join G10 G9 G4) (inner-join G12 G11 G4) (inner-join G14 G13 G4) (inner-join G16 G15 G4)
   360   │    └── [presentation: b:1,x:2,c:3,y:4,d:5,z:6,a:7,b:8,c:9,d:10]
   361   │         ├── best: (inner-join G3 G2 G4)
   362   │         └── cost: 10025691.20
   363   ├── G2: (scan bx)
   364   │    └── []
   365   │         ├── best: (scan bx)
   366   │         └── cost: 1040.02
   367   ├── G3: (inner-join G5 G7 G4) (inner-join G7 G5 G4) (inner-join G9 G13 G4) (inner-join G11 G15 G4) (inner-join G13 G9 G4) (inner-join G15 G11 G4)
   368   │    └── []
   369   │         ├── best: (inner-join G5 G7 G4)
   370   │         └── cost: 12133.67
   371   ├── G4: (filters)
   372   ├── G5: (scan cy)
   373   │    └── []
   374   │         ├── best: (scan cy)
   375   │         └── cost: 1040.02
   376   ├── G6: (inner-join G7 G2 G4) (inner-join G2 G7 G4) (inner-join G9 G16 G4) (inner-join G11 G14 G4) (inner-join G16 G9 G4) (inner-join G14 G11 G4)
   377   │    └── []
   378   │         ├── best: (inner-join G7 G2 G4)
   379   │         └── cost: 12133.67
   380   ├── G7: (inner-join G9 G11 G4) (inner-join G11 G9 G4)
   381   │    └── []
   382   │         ├── best: (inner-join G9 G11 G4)
   383   │         └── cost: 1063.64
   384   ├── G8: (inner-join G5 G2 G4) (inner-join G2 G5 G4)
   385   │    └── []
   386   │         ├── best: (inner-join G5 G2 G4)
   387   │         └── cost: 12110.05
   388   ├── G9: (scan dz)
   389   │    └── []
   390   │         ├── best: (scan dz)
   391   │         └── cost: 1040.02
   392   ├── G10: (inner-join G13 G2 G4) (inner-join G2 G13 G4) (inner-join G11 G8 G4) (inner-join G5 G16 G4) (inner-join G8 G11 G4) (inner-join G16 G5 G4)
   393   │    └── []
   394   │         ├── best: (inner-join G13 G2 G4)
   395   │         └── cost: 12133.67
   396   ├── G11: (select G17 G18) (scan abc,constrained)
   397   │    └── []
   398   │         ├── best: (scan abc,constrained)
   399   │         └── cost: 1.09
   400   ├── G12: (inner-join G15 G2 G4) (inner-join G2 G15 G4) (inner-join G9 G8 G4) (inner-join G5 G14 G4) (inner-join G8 G9 G4) (inner-join G14 G5 G4)
   401   │    └── []
   402   │         ├── best: (inner-join G15 G2 G4)
   403   │         └── cost: 10025667.58
   404   ├── G13: (inner-join G11 G5 G4) (inner-join G5 G11 G4)
   405   │    └── []
   406   │         ├── best: (inner-join G5 G11 G4)
   407   │         └── cost: 1063.64
   408   ├── G14: (inner-join G9 G2 G4) (inner-join G2 G9 G4)
   409   │    └── []
   410   │         ├── best: (inner-join G9 G2 G4)
   411   │         └── cost: 12110.05
   412   ├── G15: (inner-join G9 G5 G4) (inner-join G5 G9 G4)
   413   │    └── []
   414   │         ├── best: (inner-join G9 G5 G4)
   415   │         └── cost: 12110.05
   416   ├── G16: (inner-join G11 G2 G4) (inner-join G2 G11 G4)
   417   │    └── []
   418   │         ├── best: (inner-join G2 G11 G4)
   419   │         └── cost: 1063.64
   420   ├── G17: (scan abc)
   421   │    └── []
   422   │         ├── best: (scan abc)
   423   │         └── cost: 1080.02
   424   ├── G18: (filters G19)
   425   ├── G19: (eq G20 G21)
   426   ├── G20: (variable a)
   427   └── G21: (const 1)
   428  
   429  # Regression test for #34795.
   430  exec-ddl
   431  CREATE TABLE a (id INT8 PRIMARY KEY)
   432  ----
   433  
   434  opt join-limit=4
   435  SELECT
   436      1
   437  FROM
   438      a as a1
   439      INNER JOIN a as a2 ON 1 = a2.id
   440      INNER JOIN a AS a3 ON a1.id = a3.id
   441      CROSS JOIN a as a4
   442  WHERE
   443      a4.id = 1 AND (SELECT true FROM a WHERE a1.id = 1)
   444  ----
   445  project
   446   ├── columns: "?column?":7!null
   447   ├── fd: ()-->(7)
   448   ├── inner-join (cross)
   449   │    ├── columns: a1.id:1!null a2.id:2!null a3.id:3!null a4.id:4!null bool:6!null
   450   │    ├── key: (3)
   451   │    ├── fd: ()-->(2,4,6), (1)==(3), (3)==(1)
   452   │    ├── inner-join (lookup a)
   453   │    │    ├── columns: a1.id:1!null a2.id:2!null a3.id:3!null bool:6!null
   454   │    │    ├── key columns: [1] = [3]
   455   │    │    ├── lookup columns are key
   456   │    │    ├── key: (3)
   457   │    │    ├── fd: ()-->(2,6), (1)==(3), (3)==(1)
   458   │    │    ├── inner-join (cross)
   459   │    │    │    ├── columns: a1.id:1!null a2.id:2!null bool:6!null
   460   │    │    │    ├── key: (1)
   461   │    │    │    ├── fd: ()-->(2,6)
   462   │    │    │    ├── select
   463   │    │    │    │    ├── columns: a1.id:1!null bool:6!null
   464   │    │    │    │    ├── key: (1)
   465   │    │    │    │    ├── fd: ()-->(6)
   466   │    │    │    │    ├── ensure-distinct-on
   467   │    │    │    │    │    ├── columns: a1.id:1!null bool:6
   468   │    │    │    │    │    ├── grouping columns: a1.id:1!null
   469   │    │    │    │    │    ├── error: "more than one row returned by a subquery used as an expression"
   470   │    │    │    │    │    ├── key: (1)
   471   │    │    │    │    │    ├── fd: (1)-->(6)
   472   │    │    │    │    │    ├── left-join (cross)
   473   │    │    │    │    │    │    ├── columns: a1.id:1!null bool:6
   474   │    │    │    │    │    │    ├── scan a1
   475   │    │    │    │    │    │    │    ├── columns: a1.id:1!null
   476   │    │    │    │    │    │    │    └── key: (1)
   477   │    │    │    │    │    │    ├── project
   478   │    │    │    │    │    │    │    ├── columns: bool:6!null
   479   │    │    │    │    │    │    │    ├── fd: ()-->(6)
   480   │    │    │    │    │    │    │    ├── scan a
   481   │    │    │    │    │    │    │    └── projections
   482   │    │    │    │    │    │    │         └── true [as=bool:6]
   483   │    │    │    │    │    │    └── filters
   484   │    │    │    │    │    │         └── a1.id:1 = 1 [outer=(1), constraints=(/1: [/1 - /1]; tight), fd=()-->(1)]
   485   │    │    │    │    │    └── aggregations
   486   │    │    │    │    │         └── const-agg [as=bool:6, outer=(6)]
   487   │    │    │    │    │              └── bool:6
   488   │    │    │    │    └── filters
   489   │    │    │    │         └── bool:6 [outer=(6), constraints=(/6: [/true - /true]; tight), fd=()-->(6)]
   490   │    │    │    ├── scan a2
   491   │    │    │    │    ├── columns: a2.id:2!null
   492   │    │    │    │    ├── constraint: /2: [/1 - /1]
   493   │    │    │    │    ├── cardinality: [0 - 1]
   494   │    │    │    │    ├── key: ()
   495   │    │    │    │    └── fd: ()-->(2)
   496   │    │    │    └── filters (true)
   497   │    │    └── filters (true)
   498   │    ├── scan a4
   499   │    │    ├── columns: a4.id:4!null
   500   │    │    ├── constraint: /4: [/1 - /1]
   501   │    │    ├── cardinality: [0 - 1]
   502   │    │    ├── key: ()
   503   │    │    └── fd: ()-->(4)
   504   │    └── filters (true)
   505   └── projections
   506        └── 1 [as="?column?":7]