exec-ddl
CREATE TABLE a (x INT PRIMARY KEY, y INT, s STRING)
----
TABLE a
 ├── x int not null
 ├── y int
 ├── s string
 └── INDEX primary
      └── x int not null

exec-ddl
CREATE TABLE b (x INT, z INT NOT NULL, s STRING)
----
TABLE b
 ├── x int
 ├── z int not null
 ├── s string
 ├── rowid int not null (hidden)
 └── INDEX primary
      └── rowid int not null (hidden)

exec-ddl
CREATE TABLE c (x INT, z INT NOT NULL, s STRING)
----
TABLE c
 ├── x int
 ├── z int not null
 ├── s string
 ├── rowid int not null (hidden)
 └── INDEX primary
      └── rowid int not null (hidden)

exec-ddl
ALTER TABLE a INJECT STATISTICS '[
  {
    "columns": ["x"],
    "created_at": "2018-01-01 1:00:00.00000+00:00",
    "row_count": 5000,
    "distinct_count": 5000
  },
  {
    "columns": ["y"],
    "created_at": "2018-01-01 1:30:00.00000+00:00",
    "row_count": 5000,
    "distinct_count": 400
  },
  {
    "columns": ["s"],
    "created_at": "2018-01-01 1:30:00.00000+00:00",
    "row_count": 5000,
    "distinct_count": 10
  },
  {
    "columns": ["y","s"],
    "created_at": "2018-01-01 1:30:00.00000+00:00",
    "row_count": 5000,
    "distinct_count": 1000
  }
]'
----

exec-ddl
ALTER TABLE b INJECT STATISTICS '[
  {
    "columns": ["x"],
    "created_at": "2018-01-01 1:00:00.00000+00:00",
    "row_count": 10000,
    "distinct_count": 5000
  },
  {
    "columns": ["z"],
    "created_at": "2018-01-01 1:30:00.00000+00:00",
    "row_count": 10000,
    "distinct_count": 100
  },
  {
    "columns": ["s"],
    "created_at": "2018-01-01 1:30:00.00000+00:00",
    "row_count": 10000,
    "distinct_count": 10
  },
  {
    "columns": ["z","s"],
    "created_at": "2018-01-01 1:40:00.00000+00:00",
    "row_count": 10000,
    "distinct_count": 200
  },
  {
    "columns": ["rowid"],
    "created_at": "2018-01-01 1:30:00.00000+00:00",
    "row_count": 10000,
    "distinct_count": 10000
  }
]'
----

exec-ddl
ALTER TABLE c INJECT STATISTICS '[
  {
    "columns": ["x"],
    "created_at": "2018-01-01 1:00:00.00000+00:00",
    "row_count": 10000,
    "distinct_count": 5000
  },
  {
    "columns": ["z"],
    "created_at": "2018-01-01 1:30:00.00000+00:00",
    "row_count": 10000,
    "distinct_count": 100
  },
  {
    "columns": ["s"],
    "created_at": "2018-01-01 1:30:00.00000+00:00",
    "row_count": 10000,
    "distinct_count": 10
  }
]'
----

build
SELECT *, x FROM a UNION SELECT *, rowid FROM b
----
union
 ├── columns: x:8(int) y:9(int) s:10(string) x:11(int!null)
 ├── left columns: a.x:1(int) a.y:2(int) a.s:3(string) a.x:1(int)
 ├── right columns: b.x:4(int) z:5(int) b.s:6(string) rowid:7(int)
 ├── stats: [rows=15000, distinct(8-11)=15000]
 ├── key: (8-11)
 ├── scan a
 │    ├── columns: a.x:1(int!null) a.y:2(int) a.s:3(string)
 │    ├── stats: [rows=5000, distinct(1-3)=5000]
 │    ├── key: (1)
 │    └── fd: (1)-->(2,3)
 └── scan b
      ├── columns: b.x:4(int) z:5(int!null) b.s:6(string) rowid:7(int!null)
      ├── stats: [rows=10000, distinct(4-7)=10000]
      ├── key: (7)
      └── fd: (7)-->(4-6)

build
SELECT *, x FROM a UNION ALL SELECT *, rowid FROM b
----
union-all
 ├── columns: x:8(int) y:9(int) s:10(string) x:11(int!null)
 ├── left columns: a.x:1(int) a.y:2(int) a.s:3(string) a.x:1(int)
 ├── right columns: b.x:4(int) z:5(int) b.s:6(string) rowid:7(int)
 ├── stats: [rows=15000]
 ├── scan a
 │    ├── columns: a.x:1(int!null) a.y:2(int) a.s:3(string)
 │    ├── stats: [rows=5000]
 │    ├── key: (1)
 │    └── fd: (1)-->(2,3)
 └── scan b
      ├── columns: b.x:4(int) z:5(int!null) b.s:6(string) rowid:7(int!null)
      ├── stats: [rows=10000]
      ├── key: (7)
      └── fd: (7)-->(4-6)

build
SELECT y, s FROM a UNION SELECT z, s FROM c
----
union
 ├── columns: y:8(int) s:9(string)
 ├── left columns: a.y:2(int) a.s:3(string)
 ├── right columns: z:5(int) c.s:6(string)
 ├── stats: [rows=2000, distinct(8,9)=2000]
 ├── key: (8,9)
 ├── project
 │    ├── columns: a.y:2(int) a.s:3(string)
 │    ├── stats: [rows=5000, distinct(2,3)=1000]
 │    └── scan a
 │         ├── columns: a.x:1(int!null) a.y:2(int) a.s:3(string)
 │         ├── stats: [rows=5000, distinct(2,3)=1000]
 │         ├── key: (1)
 │         └── fd: (1)-->(2,3)
 └── project
      ├── columns: z:5(int!null) c.s:6(string)
      ├── stats: [rows=10000, distinct(5,6)=1000]
      └── scan c
           ├── columns: c.x:4(int) z:5(int!null) c.s:6(string) rowid:7(int!null)
           ├── stats: [rows=10000, distinct(5,6)=1000]
           ├── key: (7)
           └── fd: (7)-->(4-6)

build
SELECT y, s FROM a UNION SELECT z, s FROM b
----
union
 ├── columns: y:8(int) s:9(string)
 ├── left columns: a.y:2(int) a.s:3(string)
 ├── right columns: z:5(int) b.s:6(string)
 ├── stats: [rows=1200, distinct(8,9)=1200]
 ├── key: (8,9)
 ├── project
 │    ├── columns: a.y:2(int) a.s:3(string)
 │    ├── stats: [rows=5000, distinct(2,3)=1000]
 │    └── scan a
 │         ├── columns: a.x:1(int!null) a.y:2(int) a.s:3(string)
 │         ├── stats: [rows=5000, distinct(2,3)=1000]
 │         ├── key: (1)
 │         └── fd: (1)-->(2,3)
 └── project
      ├── columns: z:5(int!null) b.s:6(string)
      ├── stats: [rows=10000, distinct(5,6)=200]
      └── scan b
           ├── columns: b.x:4(int) z:5(int!null) b.s:6(string) rowid:7(int!null)
           ├── stats: [rows=10000, distinct(5,6)=200]
           ├── key: (7)
           └── fd: (7)-->(4-6)

build
SELECT y, s FROM a UNION ALL SELECT z, s FROM b
----
union-all
 ├── columns: y:8(int) s:9(string)
 ├── left columns: a.y:2(int) a.s:3(string)
 ├── right columns: z:5(int) b.s:6(string)
 ├── stats: [rows=15000]
 ├── project
 │    ├── columns: a.y:2(int) a.s:3(string)
 │    ├── stats: [rows=5000]
 │    └── scan a
 │         ├── columns: a.x:1(int!null) a.y:2(int) a.s:3(string)
 │         ├── stats: [rows=5000]
 │         ├── key: (1)
 │         └── fd: (1)-->(2,3)
 └── project
      ├── columns: z:5(int!null) b.s:6(string)
      ├── stats: [rows=10000]
      └── scan b
           ├── columns: b.x:4(int) z:5(int!null) b.s:6(string) rowid:7(int!null)
           ├── stats: [rows=10000]
           ├── key: (7)
           └── fd: (7)-->(4-6)

build
SELECT x, y, x FROM a INTERSECT SELECT z, x, rowid FROM (SELECT *, rowid FROM b WHERE b.x=1) b
----
intersect
 ├── columns: x:1(int!null) y:2(int) x:1(int!null)
 ├── left columns: a.x:1(int!null) y:2(int) a.x:1(int!null)
 ├── right columns: z:5(int) b.x:4(int) rowid:7(int)
 ├── stats: [rows=2, distinct(1,2)=2]
 ├── key: (1,2)
 ├── project
 │    ├── columns: a.x:1(int!null) y:2(int)
 │    ├── stats: [rows=5000, distinct(1,2)=5000]
 │    ├── key: (1)
 │    ├── fd: (1)-->(2)
 │    └── scan a
 │         ├── columns: a.x:1(int!null) y:2(int) a.s:3(string)
 │         ├── stats: [rows=5000, distinct(1,2)=5000]
 │         ├── key: (1)
 │         └── fd: (1)-->(2,3)
 └── project
      ├── columns: b.x:4(int!null) z:5(int!null) rowid:7(int!null)
      ├── stats: [rows=2, distinct(4,5,7)=2]
      ├── key: (7)
      ├── fd: ()-->(4), (7)-->(5)
      └── select
           ├── columns: b.x:4(int!null) z:5(int!null) b.s:6(string) rowid:7(int!null)
           ├── stats: [rows=2, distinct(4)=1, distinct(4,5,7)=2]
           ├── key: (7)
           ├── fd: ()-->(4), (7)-->(5,6)
           ├── scan b
           │    ├── columns: b.x:4(int) z:5(int!null) b.s:6(string) rowid:7(int!null)
           │    ├── stats: [rows=10000, distinct(4)=5000, distinct(4,5,7)=10000]
           │    ├── key: (7)
           │    └── fd: (7)-->(4-6)
           └── filters [type=bool, outer=(4), constraints=(/4: [/1 - /1]; tight), fd=()-->(4)]
                └── b.x = 1 [type=bool, outer=(4), constraints=(/4: [/1 - /1]; tight)]

build
SELECT x, y, x FROM a INTERSECT ALL SELECT z, x, rowid FROM (SELECT *, rowid FROM b WHERE b.x=1) b
----
intersect-all
 ├── columns: x:1(int!null) y:2(int) x:1(int!null)
 ├── left columns: a.x:1(int!null) y:2(int) a.x:1(int!null)
 ├── right columns: z:5(int) b.x:4(int) rowid:7(int)
 ├── stats: [rows=2]
 ├── project
 │    ├── columns: a.x:1(int!null) y:2(int)
 │    ├── stats: [rows=5000]
 │    ├── key: (1)
 │    ├── fd: (1)-->(2)
 │    └── scan a
 │         ├── columns: a.x:1(int!null) y:2(int) a.s:3(string)
 │         ├── stats: [rows=5000]
 │         ├── key: (1)
 │         └── fd: (1)-->(2,3)
 └── project
      ├── columns: b.x:4(int!null) z:5(int!null) rowid:7(int!null)
      ├── stats: [rows=2]
      ├── key: (7)
      ├── fd: ()-->(4), (7)-->(5)
      └── select
           ├── columns: b.x:4(int!null) z:5(int!null) b.s:6(string) rowid:7(int!null)
           ├── stats: [rows=2, distinct(4)=1]
           ├── key: (7)
           ├── fd: ()-->(4), (7)-->(5,6)
           ├── scan b
           │    ├── columns: b.x:4(int) z:5(int!null) b.s:6(string) rowid:7(int!null)
           │    ├── stats: [rows=10000, distinct(4)=5000]
           │    ├── key: (7)
           │    └── fd: (7)-->(4-6)
           └── filters [type=bool, outer=(4), constraints=(/4: [/1 - /1]; tight), fd=()-->(4)]
                └── b.x = 1 [type=bool, outer=(4), constraints=(/4: [/1 - /1]; tight)]

build
SELECT y, s FROM a INTERSECT SELECT z, s FROM c
----
intersect
 ├── columns: y:2(int) s:3(string)
 ├── left columns: y:2(int) a.s:3(string)
 ├── right columns: z:5(int) c.s:6(string)
 ├── stats: [rows=1000, distinct(2,3)=1000]
 ├── key: (2,3)
 ├── project
 │    ├── columns: y:2(int) a.s:3(string)
 │    ├── stats: [rows=5000, distinct(2,3)=1000]
 │    └── scan a
 │         ├── columns: a.x:1(int!null) y:2(int) a.s:3(string)
 │         ├── stats: [rows=5000, distinct(2,3)=1000]
 │         ├── key: (1)
 │         └── fd: (1)-->(2,3)
 └── project
      ├── columns: z:5(int!null) c.s:6(string)
      ├── stats: [rows=10000, distinct(5,6)=1000]
      └── scan c
           ├── columns: c.x:4(int) z:5(int!null) c.s:6(string) rowid:7(int!null)
           ├── stats: [rows=10000, distinct(5,6)=1000]
           ├── key: (7)
           └── fd: (7)-->(4-6)

build
SELECT y, s FROM a INTERSECT SELECT z, s FROM b
----
intersect
 ├── columns: y:2(int) s:3(string)
 ├── left columns: y:2(int) a.s:3(string)
 ├── right columns: z:5(int) b.s:6(string)
 ├── stats: [rows=200, distinct(2,3)=200]
 ├── key: (2,3)
 ├── project
 │    ├── columns: y:2(int) a.s:3(string)
 │    ├── stats: [rows=5000, distinct(2,3)=1000]
 │    └── scan a
 │         ├── columns: a.x:1(int!null) y:2(int) a.s:3(string)
 │         ├── stats: [rows=5000, distinct(2,3)=1000]
 │         ├── key: (1)
 │         └── fd: (1)-->(2,3)
 └── project
      ├── columns: z:5(int!null) b.s:6(string)
      ├── stats: [rows=10000, distinct(5,6)=200]
      └── scan b
           ├── columns: b.x:4(int) z:5(int!null) b.s:6(string) rowid:7(int!null)
           ├── stats: [rows=10000, distinct(5,6)=200]
           ├── key: (7)
           └── fd: (7)-->(4-6)

build
SELECT y, s FROM a INTERSECT ALL SELECT z, s FROM b
----
intersect-all
 ├── columns: y:2(int) s:3(string)
 ├── left columns: y:2(int) a.s:3(string)
 ├── right columns: z:5(int) b.s:6(string)
 ├── stats: [rows=5000]
 ├── project
 │    ├── columns: y:2(int) a.s:3(string)
 │    ├── stats: [rows=5000]
 │    └── scan a
 │         ├── columns: a.x:1(int!null) y:2(int) a.s:3(string)
 │         ├── stats: [rows=5000]
 │         ├── key: (1)
 │         └── fd: (1)-->(2,3)
 └── project
      ├── columns: z:5(int!null) b.s:6(string)
      ├── stats: [rows=10000]
      └── scan b
           ├── columns: b.x:4(int) z:5(int!null) b.s:6(string) rowid:7(int!null)
           ├── stats: [rows=10000]
           ├── key: (7)
           └── fd: (7)-->(4-6)

build
SELECT x, x, y FROM a EXCEPT SELECT x, z, z FROM (SELECT * FROM b WHERE b.x=1) b
----
except
 ├── columns: x:1(int!null) x:1(int!null) y:2(int)
 ├── left columns: a.x:1(int!null) a.x:1(int!null) y:2(int)
 ├── right columns: b.x:4(int) z:5(int) z:5(int)
 ├── stats: [rows=5000, distinct(1,2)=5000]
 ├── key: (1,2)
 ├── project
 │    ├── columns: a.x:1(int!null) y:2(int)
 │    ├── stats: [rows=5000, distinct(1,2)=5000]
 │    ├── key: (1)
 │    ├── fd: (1)-->(2)
 │    └── scan a
 │         ├── columns: a.x:1(int!null) y:2(int) a.s:3(string)
 │         ├── stats: [rows=5000, distinct(1,2)=5000]
 │         ├── key: (1)
 │         └── fd: (1)-->(2,3)
 └── project
      ├── columns: b.x:4(int!null) z:5(int!null)
      ├── stats: [rows=2, distinct(4,5)=2]
      ├── fd: ()-->(4)
      └── project
           ├── columns: b.x:4(int!null) z:5(int!null) b.s:6(string)
           ├── stats: [rows=2, distinct(4,5)=2]
           ├── fd: ()-->(4)
           └── select
                ├── columns: b.x:4(int!null) z:5(int!null) b.s:6(string) rowid:7(int!null)
                ├── stats: [rows=2, distinct(4)=1, distinct(4,5)=2]
                ├── key: (7)
                ├── fd: ()-->(4), (7)-->(5,6)
                ├── scan b
                │    ├── columns: b.x:4(int) z:5(int!null) b.s:6(string) rowid:7(int!null)
                │    ├── stats: [rows=10000, distinct(4)=5000, distinct(4,5)=10000]
                │    ├── key: (7)
                │    └── fd: (7)-->(4-6)
                └── filters [type=bool, outer=(4), constraints=(/4: [/1 - /1]; tight), fd=()-->(4)]
                     └── b.x = 1 [type=bool, outer=(4), constraints=(/4: [/1 - /1]; tight)]

build
SELECT x, x, y FROM a EXCEPT ALL SELECT x, z, z FROM (SELECT * FROM b WHERE b.x=1) b
----
except-all
 ├── columns: x:1(int!null) x:1(int!null) y:2(int)
 ├── left columns: a.x:1(int!null) a.x:1(int!null) y:2(int)
 ├── right columns: b.x:4(int) z:5(int) z:5(int)
 ├── stats: [rows=5000]
 ├── project
 │    ├── columns: a.x:1(int!null) y:2(int)
 │    ├── stats: [rows=5000]
 │    ├── key: (1)
 │    ├── fd: (1)-->(2)
 │    └── scan a
 │         ├── columns: a.x:1(int!null) y:2(int) a.s:3(string)
 │         ├── stats: [rows=5000]
 │         ├── key: (1)
 │         └── fd: (1)-->(2,3)
 └── project
      ├── columns: b.x:4(int!null) z:5(int!null)
      ├── stats: [rows=2]
      ├── fd: ()-->(4)
      └── project
           ├── columns: b.x:4(int!null) z:5(int!null) b.s:6(string)
           ├── stats: [rows=2]
           ├── fd: ()-->(4)
           └── select
                ├── columns: b.x:4(int!null) z:5(int!null) b.s:6(string) rowid:7(int!null)
                ├── stats: [rows=2, distinct(4)=1]
                ├── key: (7)
                ├── fd: ()-->(4), (7)-->(5,6)
                ├── scan b
                │    ├── columns: b.x:4(int) z:5(int!null) b.s:6(string) rowid:7(int!null)
                │    ├── stats: [rows=10000, distinct(4)=5000]
                │    ├── key: (7)
                │    └── fd: (7)-->(4-6)
                └── filters [type=bool, outer=(4), constraints=(/4: [/1 - /1]; tight), fd=()-->(4)]
                     └── b.x = 1 [type=bool, outer=(4), constraints=(/4: [/1 - /1]; tight)]

build
SELECT y, s FROM a EXCEPT SELECT z, s FROM c
----
except
 ├── columns: y:2(int) s:3(string)
 ├── left columns: y:2(int) a.s:3(string)
 ├── right columns: z:5(int) c.s:6(string)
 ├── stats: [rows=1000, distinct(2,3)=1000]
 ├── key: (2,3)
 ├── project
 │    ├── columns: y:2(int) a.s:3(string)
 │    ├── stats: [rows=5000, distinct(2,3)=1000]
 │    └── scan a
 │         ├── columns: a.x:1(int!null) y:2(int) a.s:3(string)
 │         ├── stats: [rows=5000, distinct(2,3)=1000]
 │         ├── key: (1)
 │         └── fd: (1)-->(2,3)
 └── project
      ├── columns: z:5(int!null) c.s:6(string)
      ├── stats: [rows=10000, distinct(5,6)=1000]
      └── scan c
           ├── columns: c.x:4(int) z:5(int!null) c.s:6(string) rowid:7(int!null)
           ├── stats: [rows=10000, distinct(5,6)=1000]
           ├── key: (7)
           └── fd: (7)-->(4-6)

build
SELECT y, s FROM a EXCEPT SELECT z, s FROM b
----
except
 ├── columns: y:2(int) s:3(string)
 ├── left columns: y:2(int) a.s:3(string)
 ├── right columns: z:5(int) b.s:6(string)
 ├── stats: [rows=1000, distinct(2,3)=1000]
 ├── key: (2,3)
 ├── project
 │    ├── columns: y:2(int) a.s:3(string)
 │    ├── stats: [rows=5000, distinct(2,3)=1000]
 │    └── scan a
 │         ├── columns: a.x:1(int!null) y:2(int) a.s:3(string)
 │         ├── stats: [rows=5000, distinct(2,3)=1000]
 │         ├── key: (1)
 │         └── fd: (1)-->(2,3)
 └── project
      ├── columns: z:5(int!null) b.s:6(string)
      ├── stats: [rows=10000, distinct(5,6)=200]
      └── scan b
           ├── columns: b.x:4(int) z:5(int!null) b.s:6(string) rowid:7(int!null)
           ├── stats: [rows=10000, distinct(5,6)=200]
           ├── key: (7)
           └── fd: (7)-->(4-6)

build
SELECT y, s FROM a EXCEPT ALL SELECT z, s FROM b
----
except-all
 ├── columns: y:2(int) s:3(string)
 ├── left columns: y:2(int) a.s:3(string)
 ├── right columns: z:5(int) b.s:6(string)
 ├── stats: [rows=5000]
 ├── project
 │    ├── columns: y:2(int) a.s:3(string)
 │    ├── stats: [rows=5000]
 │    └── scan a
 │         ├── columns: a.x:1(int!null) y:2(int) a.s:3(string)
 │         ├── stats: [rows=5000]
 │         ├── key: (1)
 │         └── fd: (1)-->(2,3)
 └── project
      ├── columns: z:5(int!null) b.s:6(string)
      ├── stats: [rows=10000]
      └── scan b
           ├── columns: b.x:4(int) z:5(int!null) b.s:6(string) rowid:7(int!null)
           ├── stats: [rows=10000]
           ├── key: (7)
           └── fd: (7)-->(4-6)

build
SELECT * FROM (SELECT y, s FROM a EXCEPT ALL SELECT z, s FROM b) WHERE y = 5
----
select
 ├── columns: y:2(int!null) s:3(string)
 ├── stats: [rows=12.5, distinct(2)=1]
 ├── fd: ()-->(2)
 ├── except-all
 │    ├── columns: y:2(int) a.s:3(string)
 │    ├── left columns: y:2(int) a.s:3(string)
 │    ├── right columns: z:5(int) b.s:6(string)
 │    ├── stats: [rows=5000, distinct(2)=400]
 │    ├── project
 │    │    ├── columns: y:2(int) a.s:3(string)
 │    │    ├── stats: [rows=5000, distinct(2)=400]
 │    │    └── scan a
 │    │         ├── columns: a.x:1(int!null) y:2(int) a.s:3(string)
 │    │         ├── stats: [rows=5000, distinct(2)=400]
 │    │         ├── key: (1)
 │    │         └── fd: (1)-->(2,3)
 │    └── project
 │         ├── columns: z:5(int!null) b.s:6(string)
 │         ├── stats: [rows=10000, distinct(5)=100]
 │         └── scan b
 │              ├── columns: b.x:4(int) z:5(int!null) b.s:6(string) rowid:7(int!null)
 │              ├── stats: [rows=10000, distinct(5)=100]
 │              ├── key: (7)
 │              └── fd: (7)-->(4-6)
 └── filters [type=bool, outer=(2), constraints=(/2: [/5 - /5]; tight), fd=()-->(2)]
      └── y = 5 [type=bool, outer=(2), constraints=(/2: [/5 - /5]; tight)]
