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, null(8-11)=0]
 ├── 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, null(1-3)=0]
 │    ├── 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, null(4-7)=0]
      ├── 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, null(8,9)=0]
 ├── key: (8,9)
 ├── project
 │    ├── columns: a.y:2(int) a.s:3(string)
 │    ├── stats: [rows=5000, distinct(2,3)=1000, null(2,3)=0]
 │    └── scan a
 │         ├── columns: a.x:1(int!null) a.y:2(int) a.s:3(string)
 │         ├── stats: [rows=5000, distinct(2,3)=1000, null(2,3)=0]
 │         ├── key: (1)
 │         └── fd: (1)-->(2,3)
 └── project
      ├── columns: z:5(int!null) c.s:6(string)
      ├── stats: [rows=10000, distinct(5,6)=1000, null(5,6)=0]
      └── 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, null(5,6)=0]
           ├── 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, null(8,9)=0]
 ├── key: (8,9)
 ├── project
 │    ├── columns: a.y:2(int) a.s:3(string)
 │    ├── stats: [rows=5000, distinct(2,3)=1000, null(2,3)=0]
 │    └── scan a
 │         ├── columns: a.x:1(int!null) a.y:2(int) a.s:3(string)
 │         ├── stats: [rows=5000, distinct(2,3)=1000, null(2,3)=0]
 │         ├── key: (1)
 │         └── fd: (1)-->(2,3)
 └── project
      ├── columns: z:5(int!null) b.s:6(string)
      ├── stats: [rows=10000, distinct(5,6)=200, null(5,6)=0]
      └── 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, null(5,6)=0]
           ├── 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, null(1,2)=0]
 ├── key: (1,2)
 ├── project
 │    ├── columns: a.x:1(int!null) y:2(int)
 │    ├── stats: [rows=5000, distinct(1,2)=5000, null(1,2)=0]
 │    ├── 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, null(1,2)=0]
 │         ├── 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, null(4,5,7)=0]
      ├── 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, null(4)=0, distinct(5)=1.98032874, null(5)=0, distinct(7)=2, null(7)=0, distinct(4,5,7)=2, null(4,5,7)=0]
           ├── 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, null(4)=0, distinct(5)=100, null(5)=0, distinct(7)=10000, null(7)=0, distinct(4,5,7)=10000, null(4,5,7)=0]
           │    ├── key: (7)
           │    └── fd: (7)-->(4-6)
           └── filters
                └── b.x = 1 [type=bool, outer=(4), constraints=(/4: [/1 - /1]; tight), fd=()-->(4)]

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, null(4)=0, distinct(5)=1.98032874, null(5)=0, distinct(7)=2, null(7)=0]
           ├── 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, null(4)=0, distinct(5)=100, null(5)=0, distinct(7)=10000, null(7)=0]
           │    ├── key: (7)
           │    └── fd: (7)-->(4-6)
           └── filters
                └── b.x = 1 [type=bool, outer=(4), constraints=(/4: [/1 - /1]; tight), fd=()-->(4)]

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, null(2,3)=0]
 ├── key: (2,3)
 ├── project
 │    ├── columns: y:2(int) a.s:3(string)
 │    ├── stats: [rows=5000, distinct(2,3)=1000, null(2,3)=0]
 │    └── scan a
 │         ├── columns: a.x:1(int!null) y:2(int) a.s:3(string)
 │         ├── stats: [rows=5000, distinct(2,3)=1000, null(2,3)=0]
 │         ├── key: (1)
 │         └── fd: (1)-->(2,3)
 └── project
      ├── columns: z:5(int!null) c.s:6(string)
      ├── stats: [rows=10000, distinct(5,6)=1000, null(5,6)=0]
      └── 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, null(5,6)=0]
           ├── 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, null(2,3)=0]
 ├── key: (2,3)
 ├── project
 │    ├── columns: y:2(int) a.s:3(string)
 │    ├── stats: [rows=5000, distinct(2,3)=1000, null(2,3)=0]
 │    └── scan a
 │         ├── columns: a.x:1(int!null) y:2(int) a.s:3(string)
 │         ├── stats: [rows=5000, distinct(2,3)=1000, null(2,3)=0]
 │         ├── key: (1)
 │         └── fd: (1)-->(2,3)
 └── project
      ├── columns: z:5(int!null) b.s:6(string)
      ├── stats: [rows=10000, distinct(5,6)=200, null(5,6)=0]
      └── 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, null(5,6)=0]
           ├── 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, null(1,2)=0]
 ├── key: (1,2)
 ├── project
 │    ├── columns: a.x:1(int!null) y:2(int)
 │    ├── stats: [rows=5000, distinct(1,2)=5000, null(1,2)=0]
 │    ├── 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, null(1,2)=0]
 │         ├── key: (1)
 │         └── fd: (1)-->(2,3)
 └── project
      ├── columns: b.x:4(int!null) z:5(int!null)
      ├── stats: [rows=2, distinct(4,5)=2, null(4,5)=0]
      ├── fd: ()-->(4)
      └── project
           ├── columns: b.x:4(int!null) z:5(int!null) b.s:6(string)
           ├── stats: [rows=2, distinct(4,5)=2, null(4,5)=0]
           ├── 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, null(4)=0, distinct(5)=1.98032874, null(5)=0, distinct(7)=2, null(7)=0, distinct(4,5)=2, null(4,5)=0]
                ├── 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, null(4)=0, distinct(5)=100, null(5)=0, distinct(7)=10000, null(7)=0, distinct(4,5)=10000, null(4,5)=0]
                │    ├── key: (7)
                │    └── fd: (7)-->(4-6)
                └── filters
                     └── b.x = 1 [type=bool, outer=(4), constraints=(/4: [/1 - /1]; tight), fd=()-->(4)]

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, null(4)=0, distinct(5)=1.98032874, null(5)=0, distinct(7)=2, null(7)=0]
                ├── 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, null(4)=0, distinct(5)=100, null(5)=0, distinct(7)=10000, null(7)=0]
                │    ├── key: (7)
                │    └── fd: (7)-->(4-6)
                └── filters
                     └── b.x = 1 [type=bool, outer=(4), constraints=(/4: [/1 - /1]; tight), fd=()-->(4)]

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, null(2,3)=0]
 ├── key: (2,3)
 ├── project
 │    ├── columns: y:2(int) a.s:3(string)
 │    ├── stats: [rows=5000, distinct(2,3)=1000, null(2,3)=0]
 │    └── scan a
 │         ├── columns: a.x:1(int!null) y:2(int) a.s:3(string)
 │         ├── stats: [rows=5000, distinct(2,3)=1000, null(2,3)=0]
 │         ├── key: (1)
 │         └── fd: (1)-->(2,3)
 └── project
      ├── columns: z:5(int!null) c.s:6(string)
      ├── stats: [rows=10000, distinct(5,6)=1000, null(5,6)=0]
      └── 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, null(5,6)=0]
           ├── 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, null(2,3)=0]
 ├── key: (2,3)
 ├── project
 │    ├── columns: y:2(int) a.s:3(string)
 │    ├── stats: [rows=5000, distinct(2,3)=1000, null(2,3)=0]
 │    └── scan a
 │         ├── columns: a.x:1(int!null) y:2(int) a.s:3(string)
 │         ├── stats: [rows=5000, distinct(2,3)=1000, null(2,3)=0]
 │         ├── key: (1)
 │         └── fd: (1)-->(2,3)
 └── project
      ├── columns: z:5(int!null) b.s:6(string)
      ├── stats: [rows=10000, distinct(5,6)=200, null(5,6)=0]
      └── 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, null(5,6)=0]
           ├── 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, null(2)=0]
 ├── 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, null(2)=0]
 │    ├── project
 │    │    ├── columns: y:2(int) a.s:3(string)
 │    │    ├── stats: [rows=5000, distinct(2)=400, null(2)=0]
 │    │    └── scan a
 │    │         ├── columns: a.x:1(int!null) y:2(int) a.s:3(string)
 │    │         ├── stats: [rows=5000, distinct(2)=400, null(2)=0]
 │    │         ├── key: (1)
 │    │         └── fd: (1)-->(2,3)
 │    └── project
 │         ├── columns: z:5(int!null) b.s:6(string)
 │         ├── stats: [rows=10000, distinct(5)=100, null(5)=0]
 │         └── 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, null(5)=0]
 │              ├── key: (7)
 │              └── fd: (7)-->(4-6)
 └── filters
      └── y = 5 [type=bool, outer=(2), constraints=(/2: [/5 - /5]; tight), fd=()-->(2)]

# Bump up null counts.
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,
    "null_count": 2500
  },
  {
    "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,
    "null_count": 5000
  },
  {
    "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,
    "null_count": 1000
  },
  {
    "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,
    "null_count": 7500
  }
]'
----

build colstat=9 colstat=10 colstat=(9,10)
SELECT x,s FROM b UNION SELECT x,s FROM c
----
union
 ├── columns: x:9(int) s:10(string)
 ├── left columns: b.x:1(int) b.s:3(string)
 ├── right columns: c.x:5(int) c.s:7(string)
 ├── stats: [rows=20000, distinct(9)=10000, null(9)=3500, distinct(10)=20, null(10)=12500, distinct(9,10)=20000, null(9,10)=14000]
 ├── key: (9,10)
 ├── project
 │    ├── columns: b.x:1(int) b.s:3(string)
 │    ├── stats: [rows=10000, distinct(1)=5000, null(1)=2500, distinct(3)=10, null(3)=5000, distinct(1,3)=10000, null(1,3)=6250]
 │    └── scan b
 │         ├── columns: b.x:1(int) b.z:2(int!null) b.s:3(string) b.rowid:4(int!null)
 │         ├── stats: [rows=10000, distinct(1)=5000, null(1)=2500, distinct(3)=10, null(3)=5000, distinct(1,3)=10000, null(1,3)=6250]
 │         ├── key: (4)
 │         └── fd: (4)-->(1-3)
 └── project
      ├── columns: c.x:5(int) c.s:7(string)
      ├── stats: [rows=10000, distinct(5)=5000, null(5)=1000, distinct(7)=10, null(7)=7500, distinct(5,7)=10000, null(5,7)=7750]
      └── scan c
           ├── columns: c.x:5(int) c.z:6(int!null) c.s:7(string) c.rowid:8(int!null)
           ├── stats: [rows=10000, distinct(5)=5000, null(5)=1000, distinct(7)=10, null(7)=7500, distinct(5,7)=10000, null(5,7)=7750]
           ├── key: (8)
           └── fd: (8)-->(5-7)

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

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

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

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

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

build colstat=9 colstat=10 colstat=(9,10)
SELECT x,s FROM b UNION ALL SELECT x,s FROM c
----
union-all
 ├── columns: x:9(int) s:10(string)
 ├── left columns: b.x:1(int) b.s:3(string)
 ├── right columns: c.x:5(int) c.s:7(string)
 ├── stats: [rows=20000, distinct(9)=10000, null(9)=3500, distinct(10)=20, null(10)=12500, distinct(9,10)=20000, null(9,10)=14000]
 ├── project
 │    ├── columns: b.x:1(int) b.s:3(string)
 │    ├── stats: [rows=10000, distinct(1)=5000, null(1)=2500, distinct(3)=10, null(3)=5000, distinct(1,3)=10000, null(1,3)=6250]
 │    └── scan b
 │         ├── columns: b.x:1(int) b.z:2(int!null) b.s:3(string) b.rowid:4(int!null)
 │         ├── stats: [rows=10000, distinct(1)=5000, null(1)=2500, distinct(3)=10, null(3)=5000, distinct(1,3)=10000, null(1,3)=6250]
 │         ├── key: (4)
 │         └── fd: (4)-->(1-3)
 └── project
      ├── columns: c.x:5(int) c.s:7(string)
      ├── stats: [rows=10000, distinct(5)=5000, null(5)=1000, distinct(7)=10, null(7)=7500, distinct(5,7)=10000, null(5,7)=7750]
      └── scan c
           ├── columns: c.x:5(int) c.z:6(int!null) c.s:7(string) c.rowid:8(int!null)
           ├── stats: [rows=10000, distinct(5)=5000, null(5)=1000, distinct(7)=10, null(7)=7500, distinct(5,7)=10000, null(5,7)=7750]
           ├── key: (8)
           └── fd: (8)-->(5-7)

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

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

# Regression test for #35715.
opt colstat=(5,2)
SELECT * FROM
((VALUES (NULL, true) EXCEPT (VALUES (1, NULL)))) AS t(a, b)
WHERE a IS NULL and b
----
select
 ├── columns: a:5(int) b:2(bool!null)
 ├── cardinality: [0 - 1]
 ├── stats: [rows=1, distinct(2)=1, null(2)=0, distinct(5)=0, null(5)=1, distinct(2,5)=0, null(2,5)=1]
 ├── key: ()
 ├── fd: ()-->(2,5)
 ├── except
 │    ├── columns: column1:5(int) column2:2(bool)
 │    ├── left columns: column1:5(int) column2:2(bool)
 │    ├── right columns: column1:3(int) column2:6(bool)
 │    ├── cardinality: [0 - 1]
 │    ├── stats: [rows=1, distinct(2)=1, null(2)=0, distinct(5)=0, null(5)=1, distinct(2,5)=0, null(2,5)=1]
 │    ├── key: (2,5)
 │    ├── values
 │    │    ├── columns: column2:2(bool) column1:5(int)
 │    │    ├── cardinality: [1 - 1]
 │    │    ├── stats: [rows=1, distinct(2)=1, null(2)=0, distinct(5)=0, null(5)=1, distinct(2,5)=0, null(2,5)=1]
 │    │    ├── key: ()
 │    │    ├── fd: ()-->(2,5)
 │    │    └── (true, NULL) [type=tuple{bool, int}]
 │    └── values
 │         ├── columns: column1:3(int) column2:6(bool)
 │         ├── cardinality: [1 - 1]
 │         ├── stats: [rows=1, distinct(3)=1, null(3)=0, distinct(6)=0, null(6)=1, distinct(3,6)=0, null(3,6)=1]
 │         ├── key: ()
 │         ├── fd: ()-->(3,6)
 │         └── (1, NULL) [type=tuple{int, bool}]
 └── filters
      ├── column1 IS NULL [type=bool, outer=(5), constraints=(/5: [/NULL - /NULL]; tight), fd=()-->(5)]
      └── variable: column2 [type=bool, outer=(2), constraints=(/2: [/true - /true]; tight), fd=()-->(2)]

# Regression test for #36147.
opt
SELECT * FROM
((VALUES (NULL, NULL), (NULL, 1), (2, NULL)) EXCEPT (VALUES (1, 2), (2, 3), (3, 4)))
WHERE column1 IS NULL
----
select
 ├── columns: column1:1(int) column2:2(int)
 ├── cardinality: [0 - 3]
 ├── stats: [rows=3, distinct(1)=1, null(1)=2]
 ├── key: (2)
 ├── fd: ()-->(1)
 ├── except
 │    ├── columns: column1:1(int) column2:2(int)
 │    ├── left columns: column1:1(int) column2:2(int)
 │    ├── right columns: column1:3(int) column2:4(int)
 │    ├── cardinality: [0 - 3]
 │    ├── stats: [rows=3, distinct(1)=1, null(1)=2, distinct(1,2)=0, null(1,2)=3]
 │    ├── key: (1,2)
 │    ├── values
 │    │    ├── columns: column1:1(int) column2:2(int)
 │    │    ├── cardinality: [3 - 3]
 │    │    ├── stats: [rows=3, distinct(1)=1, null(1)=2, distinct(1,2)=0, null(1,2)=3]
 │    │    ├── (NULL, NULL) [type=tuple{int, int}]
 │    │    ├── (NULL, 1) [type=tuple{int, int}]
 │    │    └── (2, NULL) [type=tuple{int, int}]
 │    └── values
 │         ├── columns: column1:3(int) column2:4(int)
 │         ├── cardinality: [3 - 3]
 │         ├── stats: [rows=3, distinct(3)=3, null(3)=0, distinct(3,4)=3, null(3,4)=0]
 │         ├── (1, 2) [type=tuple{int, int}]
 │         ├── (2, 3) [type=tuple{int, int}]
 │         └── (3, 4) [type=tuple{int, int}]
 └── filters
      └── column1 IS NULL [type=bool, outer=(1), constraints=(/1: [/NULL - /NULL]; tight), fd=()-->(1)]
