From 82e4452ff549ede9f34684d363f66291a3bb632b Mon Sep 17 00:00:00 2001 From: Ashutosh Bapat Date: Tue, 7 Feb 2017 11:57:30 +0530 Subject: [PATCH 07/11] Partition-wise join tests. This file does not contain tests for joins between multi-leveled partitioned tables. Those will be added later. --- src/test/regress/expected/partition_join.out | 4114 ++++++++++++++++++++++++++ src/test/regress/parallel_schedule | 2 +- src/test/regress/serial_schedule | 1 + src/test/regress/sql/partition_join.sql | 515 ++++ 4 files changed, 4631 insertions(+), 1 deletion(-) create mode 100644 src/test/regress/expected/partition_join.out create mode 100644 src/test/regress/sql/partition_join.sql diff --git a/src/test/regress/expected/partition_join.out b/src/test/regress/expected/partition_join.out new file mode 100644 index 0000000..18238fa --- /dev/null +++ b/src/test/regress/expected/partition_join.out @@ -0,0 +1,4114 @@ +-- +-- PARTITION_JOIN +-- Test partition-wise join between partitioned tables +-- +-- +-- partitioned by a single column +-- +CREATE TABLE prt1 (a int, b int, c varchar) PARTITION BY RANGE(a); +CREATE TABLE prt1_p1 PARTITION OF prt1 FOR VALUES FROM (0) TO (250); +CREATE TABLE prt1_p3 PARTITION OF prt1 FOR VALUES FROM (500) TO (600); +CREATE TABLE prt1_p2 PARTITION OF prt1 FOR VALUES FROM (250) TO (500); +INSERT INTO prt1 SELECT i, i, to_char(i, 'FM0000') FROM generate_series(0, 599, 2) i; +ANALYZE prt1; +ANALYZE prt1_p1; +ANALYZE prt1_p2; +ANALYZE prt1_p3; +-- TODO: This table is created only for testing the results. Remove once +-- results are tested. +CREATE TABLE uprt1 AS SELECT * FROM prt1; +CREATE TABLE prt2 (a int, b int, c varchar) PARTITION BY RANGE(b); +CREATE TABLE prt2_p1 PARTITION OF prt2 FOR VALUES FROM (0) TO (250); +CREATE TABLE prt2_p2 PARTITION OF prt2 FOR VALUES FROM (250) TO (500); +CREATE TABLE prt2_p3 PARTITION OF prt2 FOR VALUES FROM (500) TO (600); +INSERT INTO prt2 SELECT i, i, to_char(i, 'FM0000') FROM generate_series(0, 599, 3) i; +-- TODO: This table is created only for testing the results. Remove once +-- results are tested. +ANALYZE prt2; +ANALYZE prt2_p1; +ANALYZE prt2_p2; +ANALYZE prt2_p3; +CREATE TABLE uprt2 AS SELECT * FROM prt2; +-- inner join +EXPLAIN (VERBOSE, COSTS OFF) +SELECT t1.a, t1.c, t2.b, t2.c FROM prt1 t1, prt2 t2 WHERE t1.a = t2.b AND t1.a % 25 = 0 ORDER BY t1.a, t2.b; + QUERY PLAN +--------------------------------------------------------- + Sort + Output: t1.a, t1.c, t2.b, t2.c + Sort Key: t1.a + -> Append + -> Hash Join + Output: t1.a, t1.c, t2.b, t2.c + Hash Cond: (t2.b = t1.a) + -> Seq Scan on public.prt2_p1 t2 + Output: t2.b, t2.c + -> Hash + Output: t1.a, t1.c + -> Seq Scan on public.prt1_p1 t1 + Output: t1.a, t1.c + Filter: ((t1.a % 25) = 0) + -> Hash Join + Output: t1_2.a, t1_2.c, t2_1.b, t2_1.c + Hash Cond: (t2_1.b = t1_2.a) + -> Seq Scan on public.prt2_p2 t2_1 + Output: t2_1.b, t2_1.c + -> Hash + Output: t1_2.a, t1_2.c + -> Seq Scan on public.prt1_p2 t1_2 + Output: t1_2.a, t1_2.c + Filter: ((t1_2.a % 25) = 0) + -> Hash Join + Output: t1_1.a, t1_1.c, t2_2.b, t2_2.c + Hash Cond: (t2_2.b = t1_1.a) + -> Seq Scan on public.prt2_p3 t2_2 + Output: t2_2.b, t2_2.c + -> Hash + Output: t1_1.a, t1_1.c + -> Seq Scan on public.prt1_p3 t1_1 + Output: t1_1.a, t1_1.c + Filter: ((t1_1.a % 25) = 0) +(34 rows) + +SELECT t1.a, t1.c, t2.b, t2.c FROM prt1 t1, prt2 t2 WHERE t1.a = t2.b AND t1.a % 25 = 0 ORDER BY t1.a, t2.b; + a | c | b | c +-----+------+-----+------ + 0 | 0000 | 0 | 0000 + 150 | 0150 | 150 | 0150 + 300 | 0300 | 300 | 0300 + 450 | 0450 | 450 | 0450 +(4 rows) + +SELECT t1.a, t1.c, t2.b, t2.c FROM uprt1 t1, uprt2 t2 WHERE t1.a = t2.b AND t1.a % 25 = 0 ORDER BY t1.a, t2.b; + a | c | b | c +-----+------+-----+------ + 0 | 0000 | 0 | 0000 + 150 | 0150 | 150 | 0150 + 300 | 0300 | 300 | 0300 + 450 | 0450 | 450 | 0450 +(4 rows) + +-- left outer join +EXPLAIN (VERBOSE, COSTS OFF) +SELECT t1.a, t1.c, t2.b, t2.c FROM prt1 t1 LEFT JOIN prt2 t2 ON t1.a = t2.b WHERE t1.a % 25 = 0 ORDER BY t1.a, t2.b; + QUERY PLAN +--------------------------------------------------------- + Sort + Output: t1.a, t1.c, t2.b, t2.c + Sort Key: t1.a, t2.b + -> Append + -> Hash Right Join + Output: t1.a, t1.c, t2.b, t2.c + Hash Cond: (t2.b = t1.a) + -> Seq Scan on public.prt2_p1 t2 + Output: t2.b, t2.c + -> Hash + Output: t1.a, t1.c + -> Seq Scan on public.prt1_p1 t1 + Output: t1.a, t1.c + Filter: ((t1.a % 25) = 0) + -> Hash Right Join + Output: t1_2.a, t1_2.c, t2_1.b, t2_1.c + Hash Cond: (t2_1.b = t1_2.a) + -> Seq Scan on public.prt2_p2 t2_1 + Output: t2_1.b, t2_1.c + -> Hash + Output: t1_2.a, t1_2.c + -> Seq Scan on public.prt1_p2 t1_2 + Output: t1_2.a, t1_2.c + Filter: ((t1_2.a % 25) = 0) + -> Hash Right Join + Output: t1_1.a, t1_1.c, t2_2.b, t2_2.c + Hash Cond: (t2_2.b = t1_1.a) + -> Seq Scan on public.prt2_p3 t2_2 + Output: t2_2.b, t2_2.c + -> Hash + Output: t1_1.a, t1_1.c + -> Seq Scan on public.prt1_p3 t1_1 + Output: t1_1.a, t1_1.c + Filter: ((t1_1.a % 25) = 0) +(34 rows) + +SELECT t1.a, t1.c, t2.b, t2.c FROM prt1 t1 LEFT JOIN prt2 t2 ON t1.a = t2.b WHERE t1.a % 25 = 0 ORDER BY t1.a, t2.b; + a | c | b | c +-----+------+-----+------ + 0 | 0000 | 0 | 0000 + 50 | 0050 | | + 100 | 0100 | | + 150 | 0150 | 150 | 0150 + 200 | 0200 | | + 250 | 0250 | | + 300 | 0300 | 300 | 0300 + 350 | 0350 | | + 400 | 0400 | | + 450 | 0450 | 450 | 0450 + 500 | 0500 | | + 550 | 0550 | | +(12 rows) + +SELECT t1.a, t1.c, t2.b, t2.c FROM uprt1 t1 LEFT JOIN uprt2 t2 ON t1.a = t2.b WHERE t1.a % 25 = 0 ORDER BY t1.a, t2.b; + a | c | b | c +-----+------+-----+------ + 0 | 0000 | 0 | 0000 + 50 | 0050 | | + 100 | 0100 | | + 150 | 0150 | 150 | 0150 + 200 | 0200 | | + 250 | 0250 | | + 300 | 0300 | 300 | 0300 + 350 | 0350 | | + 400 | 0400 | | + 450 | 0450 | 450 | 0450 + 500 | 0500 | | + 550 | 0550 | | +(12 rows) + +-- right outer join +EXPLAIN (VERBOSE, COSTS OFF) +SELECT t1.a, t1.c, t2.b, t2.c FROM prt1 t1 RIGHT JOIN prt2 t2 ON t1.a = t2.b WHERE t2.b % 25 = 0 ORDER BY t1.a, t2.b; + QUERY PLAN +--------------------------------------------------------------- + Sort + Output: t1.a, t1.c, t2.b, t2.c + Sort Key: t1.a, t2.b + -> Result + Output: t1.a, t1.c, t2.b, t2.c + -> Append + -> Hash Right Join + Output: t2.b, t2.c, t1.a, t1.c + Hash Cond: (t1.a = t2.b) + -> Seq Scan on public.prt1_p1 t1 + Output: t1.a, t1.c + -> Hash + Output: t2.b, t2.c + -> Seq Scan on public.prt2_p1 t2 + Output: t2.b, t2.c + Filter: ((t2.b % 25) = 0) + -> Hash Right Join + Output: t2_1.b, t2_1.c, t1_2.a, t1_2.c + Hash Cond: (t1_2.a = t2_1.b) + -> Seq Scan on public.prt1_p2 t1_2 + Output: t1_2.a, t1_2.c + -> Hash + Output: t2_1.b, t2_1.c + -> Seq Scan on public.prt2_p2 t2_1 + Output: t2_1.b, t2_1.c + Filter: ((t2_1.b % 25) = 0) + -> Hash Right Join + Output: t2_2.b, t2_2.c, t1_1.a, t1_1.c + Hash Cond: (t1_1.a = t2_2.b) + -> Seq Scan on public.prt1_p3 t1_1 + Output: t1_1.a, t1_1.c + -> Hash + Output: t2_2.b, t2_2.c + -> Seq Scan on public.prt2_p3 t2_2 + Output: t2_2.b, t2_2.c + Filter: ((t2_2.b % 25) = 0) +(36 rows) + +SELECT t1.a, t1.c, t2.b, t2.c FROM prt1 t1 RIGHT JOIN prt2 t2 ON t1.a = t2.b WHERE t2.b % 25 = 0 ORDER BY t1.a, t2.b; + a | c | b | c +-----+------+-----+------ + 0 | 0000 | 0 | 0000 + 150 | 0150 | 150 | 0150 + 300 | 0300 | 300 | 0300 + 450 | 0450 | 450 | 0450 + | | 75 | 0075 + | | 225 | 0225 + | | 375 | 0375 + | | 525 | 0525 +(8 rows) + +SELECT t1.a, t1.c, t2.b, t2.c FROM uprt1 t1 RIGHT JOIN uprt2 t2 ON t1.a = t2.b WHERE t2.b % 25 = 0 ORDER BY t1.a, t2.b; + a | c | b | c +-----+------+-----+------ + 0 | 0000 | 0 | 0000 + 150 | 0150 | 150 | 0150 + 300 | 0300 | 300 | 0300 + 450 | 0450 | 450 | 0450 + | | 75 | 0075 + | | 225 | 0225 + | | 375 | 0375 + | | 525 | 0525 +(8 rows) + +-- full outer join +EXPLAIN (VERBOSE, COSTS OFF) +SELECT t1.a, t1.c, t2.b, t2.c FROM (SELECT * FROM prt1 WHERE prt1.a % 25 = 0) t1 FULL JOIN (SELECT * FROM prt2 WHERE prt2.b % 25 = 0) t2 ON (t1.a = t2.b) ORDER BY t1.a, t2.b; + QUERY PLAN +------------------------------------------------------------------ + Sort + Output: prt1_p1.a, prt1_p1.c, prt2_p1.b, prt2_p1.c + Sort Key: prt1_p1.a, prt2_p1.b + -> Append + -> Hash Full Join + Output: prt1_p1.a, prt1_p1.c, prt2_p1.b, prt2_p1.c + Hash Cond: (prt1_p1.a = prt2_p1.b) + -> Seq Scan on public.prt1_p1 + Output: prt1_p1.a, prt1_p1.c + Filter: ((prt1_p1.a % 25) = 0) + -> Hash + Output: prt2_p1.b, prt2_p1.c + -> Seq Scan on public.prt2_p1 + Output: prt2_p1.b, prt2_p1.c + Filter: ((prt2_p1.b % 25) = 0) + -> Hash Full Join + Output: prt1_p2.a, prt1_p2.c, prt2_p2.b, prt2_p2.c + Hash Cond: (prt1_p2.a = prt2_p2.b) + -> Seq Scan on public.prt1_p2 + Output: prt1_p2.a, prt1_p2.c + Filter: ((prt1_p2.a % 25) = 0) + -> Hash + Output: prt2_p2.b, prt2_p2.c + -> Seq Scan on public.prt2_p2 + Output: prt2_p2.b, prt2_p2.c + Filter: ((prt2_p2.b % 25) = 0) + -> Hash Full Join + Output: prt1_p3.a, prt1_p3.c, prt2_p3.b, prt2_p3.c + Hash Cond: (prt1_p3.a = prt2_p3.b) + -> Seq Scan on public.prt1_p3 + Output: prt1_p3.a, prt1_p3.c + Filter: ((prt1_p3.a % 25) = 0) + -> Hash + Output: prt2_p3.b, prt2_p3.c + -> Seq Scan on public.prt2_p3 + Output: prt2_p3.b, prt2_p3.c + Filter: ((prt2_p3.b % 25) = 0) +(37 rows) + +SELECT t1.a, t1.c, t2.b, t2.c FROM (SELECT * FROM prt1 WHERE prt1.a % 25 = 0) t1 FULL JOIN (SELECT * FROM prt2 WHERE prt2.b % 25 = 0) t2 ON (t1.a = t2.b) ORDER BY t1.a, t2.b; + a | c | b | c +-----+------+-----+------ + 0 | 0000 | 0 | 0000 + 50 | 0050 | | + 100 | 0100 | | + 150 | 0150 | 150 | 0150 + 200 | 0200 | | + 250 | 0250 | | + 300 | 0300 | 300 | 0300 + 350 | 0350 | | + 400 | 0400 | | + 450 | 0450 | 450 | 0450 + 500 | 0500 | | + 550 | 0550 | | + | | 75 | 0075 + | | 225 | 0225 + | | 375 | 0375 + | | 525 | 0525 +(16 rows) + +SELECT t1.a, t1.c, t2.b, t2.c FROM (SELECT * FROM uprt1 t1 WHERE t1.a % 25 = 0) t1 FULL JOIN (SELECT * FROM uprt2 t2 WHERE t2.b % 25 = 0) t2 ON (t1.a = t2.b) ORDER BY t1.a, t2.b; + a | c | b | c +-----+------+-----+------ + 0 | 0000 | 0 | 0000 + 50 | 0050 | | + 100 | 0100 | | + 150 | 0150 | 150 | 0150 + 200 | 0200 | | + 250 | 0250 | | + 300 | 0300 | 300 | 0300 + 350 | 0350 | | + 400 | 0400 | | + 450 | 0450 | 450 | 0450 + 500 | 0500 | | + 550 | 0550 | | + | | 75 | 0075 + | | 225 | 0225 + | | 375 | 0375 + | | 525 | 0525 +(16 rows) + +-- Cases with non-nullable expressions in subquery results; +-- make sure these go to null as expected +EXPLAIN (VERBOSE, COSTS OFF) +SELECT t1.a, t1.c, t2.b, t2.c FROM (SELECT 50 phv, * FROM prt1 WHERE prt1.a % 25 = 0) t1 FULL JOIN (SELECT 75 phv, * FROM prt2 WHERE prt2.b % 25 = 0) t2 ON (t1.a = t2.b) WHERE t1.phv = t1.b OR t2.phv = t2.b ORDER BY t1.a, t2.b; + QUERY PLAN +------------------------------------------------------------------ + Sort + Output: prt1_p1.a, prt1_p1.c, prt2_p1.b, prt2_p1.c + Sort Key: prt1_p1.a, prt2_p1.b + -> Append + -> Hash Full Join + Output: prt1_p1.a, prt1_p1.c, prt2_p1.b, prt2_p1.c + Hash Cond: (prt1_p1.a = prt2_p1.b) + Filter: (((50) = prt1_p1.b) OR ((75) = prt2_p1.b)) + -> Seq Scan on public.prt1_p1 + Output: prt1_p1.a, prt1_p1.c, prt1_p1.b, 50 + Filter: ((prt1_p1.a % 25) = 0) + -> Hash + Output: prt2_p1.b, prt2_p1.c, (75) + -> Seq Scan on public.prt2_p1 + Output: prt2_p1.b, prt2_p1.c, 75 + Filter: ((prt2_p1.b % 25) = 0) + -> Hash Full Join + Output: prt1_p2.a, prt1_p2.c, prt2_p2.b, prt2_p2.c + Hash Cond: (prt1_p2.a = prt2_p2.b) + Filter: (((50) = prt1_p2.b) OR ((75) = prt2_p2.b)) + -> Seq Scan on public.prt1_p2 + Output: prt1_p2.a, prt1_p2.c, prt1_p2.b, 50 + Filter: ((prt1_p2.a % 25) = 0) + -> Hash + Output: prt2_p2.b, prt2_p2.c, (75) + -> Seq Scan on public.prt2_p2 + Output: prt2_p2.b, prt2_p2.c, 75 + Filter: ((prt2_p2.b % 25) = 0) + -> Hash Full Join + Output: prt1_p3.a, prt1_p3.c, prt2_p3.b, prt2_p3.c + Hash Cond: (prt1_p3.a = prt2_p3.b) + Filter: (((50) = prt1_p3.b) OR ((75) = prt2_p3.b)) + -> Seq Scan on public.prt1_p3 + Output: prt1_p3.a, prt1_p3.c, prt1_p3.b, 50 + Filter: ((prt1_p3.a % 25) = 0) + -> Hash + Output: prt2_p3.b, prt2_p3.c, (75) + -> Seq Scan on public.prt2_p3 + Output: prt2_p3.b, prt2_p3.c, 75 + Filter: ((prt2_p3.b % 25) = 0) +(40 rows) + +SELECT t1.a, t1.c, t2.b, t2.c FROM (SELECT 50 phv, * FROM prt1 WHERE prt1.a % 25 = 0) t1 FULL JOIN (SELECT 75 phv, * FROM prt2 WHERE prt2.b % 25 = 0) t2 ON (t1.a = t2.b) WHERE t1.phv = t1.b OR t2.phv = t2.b ORDER BY t1.a, t2.b; + a | c | b | c +----+------+----+------ + 50 | 0050 | | + | | 75 | 0075 +(2 rows) + +SELECT t1.a, t1.c, t2.b, t2.c FROM (SELECT 50 phv, * FROM uprt1 WHERE uprt1.a % 25 = 0) t1 FULL JOIN (SELECT 75 phv, * FROM uprt2 WHERE uprt2.b % 25 = 0) t2 ON (t1.a = t2.b) WHERE t1.phv = t1.b OR t2.phv = t2.b ORDER BY t1.a, t2.b; + a | c | b | c +----+------+----+------ + 50 | 0050 | | + | | 75 | 0075 +(2 rows) + +EXPLAIN (VERBOSE, COSTS OFF) +SELECT t1.a, t1.c, t1.phv, t2.b, t2.c, t2.phv FROM (SELECT 25 phv, * FROM prt1 WHERE prt1.a % 25 = 0) t1 FULL JOIN (SELECT 50 phv, * FROM prt2 WHERE prt2.b % 25 = 0) t2 ON (t1.a = t2.b) ORDER BY t1.a, t2.b; + QUERY PLAN +------------------------------------------------------------------------------------ + Sort + Output: prt1_p1.a, prt1_p1.c, (25), prt2_p1.b, prt2_p1.c, (50) + Sort Key: prt1_p1.a, prt2_p1.b + -> Result + Output: prt1_p1.a, prt1_p1.c, (25), prt2_p1.b, prt2_p1.c, (50) + -> Append + -> Hash Full Join + Output: prt1_p1.a, prt1_p1.c, prt2_p1.b, prt2_p1.c, (25), (50) + Hash Cond: (prt1_p1.a = prt2_p1.b) + -> Seq Scan on public.prt1_p1 + Output: prt1_p1.a, prt1_p1.c, 25 + Filter: ((prt1_p1.a % 25) = 0) + -> Hash + Output: prt2_p1.b, prt2_p1.c, (50) + -> Seq Scan on public.prt2_p1 + Output: prt2_p1.b, prt2_p1.c, 50 + Filter: ((prt2_p1.b % 25) = 0) + -> Hash Full Join + Output: prt1_p2.a, prt1_p2.c, prt2_p2.b, prt2_p2.c, (25), (50) + Hash Cond: (prt1_p2.a = prt2_p2.b) + -> Seq Scan on public.prt1_p2 + Output: prt1_p2.a, prt1_p2.c, 25 + Filter: ((prt1_p2.a % 25) = 0) + -> Hash + Output: prt2_p2.b, prt2_p2.c, (50) + -> Seq Scan on public.prt2_p2 + Output: prt2_p2.b, prt2_p2.c, 50 + Filter: ((prt2_p2.b % 25) = 0) + -> Hash Full Join + Output: prt1_p3.a, prt1_p3.c, prt2_p3.b, prt2_p3.c, (25), (50) + Hash Cond: (prt1_p3.a = prt2_p3.b) + -> Seq Scan on public.prt1_p3 + Output: prt1_p3.a, prt1_p3.c, 25 + Filter: ((prt1_p3.a % 25) = 0) + -> Hash + Output: prt2_p3.b, prt2_p3.c, (50) + -> Seq Scan on public.prt2_p3 + Output: prt2_p3.b, prt2_p3.c, 50 + Filter: ((prt2_p3.b % 25) = 0) +(39 rows) + +SELECT t1.a, t1.c, t1.phv, t2.b, t2.c, t2.phv FROM (SELECT 25 phv, * FROM prt1 WHERE prt1.a % 25 = 0) t1 FULL JOIN (SELECT 50 phv, * FROM prt2 WHERE prt2.b % 25 = 0) t2 ON (t1.a = t2.b) ORDER BY t1.a, t2.b; + a | c | phv | b | c | phv +-----+------+-----+-----+------+----- + 0 | 0000 | 25 | 0 | 0000 | 50 + 50 | 0050 | 25 | | | + 100 | 0100 | 25 | | | + 150 | 0150 | 25 | 150 | 0150 | 50 + 200 | 0200 | 25 | | | + 250 | 0250 | 25 | | | + 300 | 0300 | 25 | 300 | 0300 | 50 + 350 | 0350 | 25 | | | + 400 | 0400 | 25 | | | + 450 | 0450 | 25 | 450 | 0450 | 50 + 500 | 0500 | 25 | | | + 550 | 0550 | 25 | | | + | | | 75 | 0075 | 50 + | | | 225 | 0225 | 50 + | | | 375 | 0375 | 50 + | | | 525 | 0525 | 50 +(16 rows) + +SELECT t1.a, t1.c, t1.phv, t2.b, t2.c, t2.phv FROM (SELECT 25 phv, * FROM uprt1 WHERE uprt1.a % 25 = 0) t1 FULL JOIN (SELECT 50 phv, * FROM uprt2 WHERE uprt2.b % 25 = 0) t2 ON (t1.a = t2.b) ORDER BY t1.a, t2.b; + a | c | phv | b | c | phv +-----+------+-----+-----+------+----- + 0 | 0000 | 25 | 0 | 0000 | 50 + 50 | 0050 | 25 | | | + 100 | 0100 | 25 | | | + 150 | 0150 | 25 | 150 | 0150 | 50 + 200 | 0200 | 25 | | | + 250 | 0250 | 25 | | | + 300 | 0300 | 25 | 300 | 0300 | 50 + 350 | 0350 | 25 | | | + 400 | 0400 | 25 | | | + 450 | 0450 | 25 | 450 | 0450 | 50 + 500 | 0500 | 25 | | | + 550 | 0550 | 25 | | | + | | | 75 | 0075 | 50 + | | | 225 | 0225 | 50 + | | | 375 | 0375 | 50 + | | | 525 | 0525 | 50 +(16 rows) + +-- Join with pruned partitions from joining relations +EXPLAIN (VERBOSE, COSTS OFF) +SELECT t1.a, t1.c, t2.b, t2.c FROM prt1 t1, prt2 t2 WHERE t1.a = t2.b AND t1.a < 450 AND t2.b > 250 AND t1.a % 25 = 0 ORDER BY t1.a, t2.b; + QUERY PLAN +------------------------------------------------------------------------ + Sort + Output: t1.a, t1.c, t2.b, t2.c + Sort Key: t1.a + -> Append + -> Hash Join + Output: t1.a, t1.c, t2.b, t2.c + Hash Cond: (t2.b = t1.a) + -> Seq Scan on public.prt2_p2 t2 + Output: t2.b, t2.c + Filter: (t2.b > 250) + -> Hash + Output: t1.a, t1.c + -> Seq Scan on public.prt1_p2 t1 + Output: t1.a, t1.c + Filter: ((t1.a < 450) AND ((t1.a % 25) = 0)) +(15 rows) + +SELECT t1.a, t1.c, t2.b, t2.c FROM prt1 t1, prt2 t2 WHERE t1.a = t2.b AND t1.a < 450 AND t2.b > 250 AND t1.a % 25 = 0 ORDER BY t1.a, t2.b; + a | c | b | c +-----+------+-----+------ + 300 | 0300 | 300 | 0300 +(1 row) + +SELECT t1.a, t1.c, t2.b, t2.c FROM uprt1 t1, uprt2 t2 WHERE t1.a = t2.b AND t1.a < 450 AND t2.b > 250 AND t1.a % 25 = 0 ORDER BY t1.a, t2.b; + a | c | b | c +-----+------+-----+------ + 300 | 0300 | 300 | 0300 +(1 row) + +EXPLAIN (VERBOSE, COSTS OFF) +SELECT t1.a, t1.c, t2.b, t2.c FROM (SELECT * FROM prt1 WHERE a < 450) t1 LEFT JOIN (SELECT * FROM prt2 WHERE b > 250) t2 ON t1.a = t2.b WHERE t1.a % 25 = 0 ORDER BY t1.a, t2.b; + QUERY PLAN +---------------------------------------------------------------------------------- + Sort + Output: prt1_p1.a, prt1_p1.c, b, c + Sort Key: prt1_p1.a, b + -> Append + -> Nested Loop Left Join + Output: prt1_p1.a, prt1_p1.c, b, c + Join Filter: (prt1_p1.a = b) + -> Seq Scan on public.prt1_p1 + Output: prt1_p1.a, prt1_p1.c + Filter: ((prt1_p1.a < 450) AND ((prt1_p1.a % 25) = 0)) + -> Result + Output: b, c + One-Time Filter: false + -> Hash Right Join + Output: prt1_p2.a, prt1_p2.c, prt2_p2.b, prt2_p2.c + Hash Cond: (prt2_p2.b = prt1_p2.a) + -> Seq Scan on public.prt2_p2 + Output: prt2_p2.b, prt2_p2.c + Filter: (prt2_p2.b > 250) + -> Hash + Output: prt1_p2.a, prt1_p2.c + -> Seq Scan on public.prt1_p2 + Output: prt1_p2.a, prt1_p2.c + Filter: ((prt1_p2.a < 450) AND ((prt1_p2.a % 25) = 0)) +(24 rows) + +SELECT t1.a, t1.c, t2.b, t2.c FROM (SELECT * FROM prt1 WHERE a < 450) t1 LEFT JOIN (SELECT * FROM prt2 WHERE b > 250) t2 ON t1.a = t2.b WHERE t1.a % 25 = 0 ORDER BY t1.a, t2.b; + a | c | b | c +-----+------+-----+------ + 0 | 0000 | | + 50 | 0050 | | + 100 | 0100 | | + 150 | 0150 | | + 200 | 0200 | | + 250 | 0250 | | + 300 | 0300 | 300 | 0300 + 350 | 0350 | | + 400 | 0400 | | +(9 rows) + +SELECT t1.a, t1.c, t2.b, t2.c FROM (SELECT * FROM uprt1 WHERE a < 450) t1 LEFT JOIN (SELECT * FROM uprt2 WHERE b > 250) t2 ON t1.a = t2.b WHERE t1.a % 25 = 0 ORDER BY t1.a, t2.b; + a | c | b | c +-----+------+-----+------ + 0 | 0000 | | + 50 | 0050 | | + 100 | 0100 | | + 150 | 0150 | | + 200 | 0200 | | + 250 | 0250 | | + 300 | 0300 | 300 | 0300 + 350 | 0350 | | + 400 | 0400 | | +(9 rows) + +EXPLAIN (VERBOSE, COSTS OFF) +SELECT t1.a, t1.c, t2.b, t2.c FROM (SELECT * FROM prt1 WHERE a < 450) t1 RIGHT JOIN (SELECT * FROM prt2 WHERE b > 250) t2 ON t1.a = t2.b WHERE t2.a % 25 = 0 ORDER BY t1.a, t2.b; + QUERY PLAN +---------------------------------------------------------------------------------------- + Sort + Output: prt1_p2.a, prt1_p2.c, prt2_p2.b, prt2_p2.c + Sort Key: prt1_p2.a, prt2_p2.b + -> Result + Output: prt1_p2.a, prt1_p2.c, prt2_p2.b, prt2_p2.c + -> Append + -> Hash Right Join + Output: prt2_p2.b, prt2_p2.c, prt1_p2.a, prt1_p2.c + Hash Cond: (prt1_p2.a = prt2_p2.b) + -> Seq Scan on public.prt1_p2 + Output: prt1_p2.a, prt1_p2.c + Filter: (prt1_p2.a < 450) + -> Hash + Output: prt2_p2.b, prt2_p2.c + -> Seq Scan on public.prt2_p2 + Output: prt2_p2.b, prt2_p2.c + Filter: ((prt2_p2.b > 250) AND ((prt2_p2.a % 25) = 0)) + -> Nested Loop Left Join + Output: prt2_p3.b, prt2_p3.c, a, c + Join Filter: (a = prt2_p3.b) + -> Seq Scan on public.prt2_p3 + Output: prt2_p3.b, prt2_p3.c + Filter: ((prt2_p3.b > 250) AND ((prt2_p3.a % 25) = 0)) + -> Result + Output: a, c + One-Time Filter: false +(26 rows) + +SELECT t1.a, t1.c, t2.b, t2.c FROM (SELECT * FROM prt1 WHERE a < 450) t1 RIGHT JOIN (SELECT * FROM prt2 WHERE b > 250) t2 ON t1.a = t2.b WHERE t2.a % 25 = 0 ORDER BY t1.a, t2.b; + a | c | b | c +-----+------+-----+------ + 300 | 0300 | 300 | 0300 + | | 375 | 0375 + | | 450 | 0450 + | | 525 | 0525 +(4 rows) + +SELECT t1.a, t1.c, t2.b, t2.c FROM (SELECT * FROM uprt1 WHERE a < 450) t1 RIGHT JOIN (SELECT * FROM uprt2 WHERE b > 250) t2 ON t1.a = t2.b WHERE t2.a % 25 = 0 ORDER BY t1.a, t2.b; + a | c | b | c +-----+------+-----+------ + 300 | 0300 | 300 | 0300 + | | 375 | 0375 + | | 450 | 0450 + | | 525 | 0525 +(4 rows) + +EXPLAIN (VERBOSE, COSTS OFF) +SELECT t1.a, t1.c, t2.b, t2.c FROM (SELECT * FROM prt1 WHERE a < 450 AND a % 25 = 0) t1 FULL JOIN (SELECT * FROM prt2 WHERE b > 250 AND b % 25 = 0) t2 ON t1.a = t2.b ORDER BY t1.a, t2.b; + QUERY PLAN +---------------------------------------------------------------------------------- + Sort + Output: prt1_p1.a, prt1_p1.c, b, c + Sort Key: prt1_p1.a, b + -> Append + -> Hash Full Join + Output: prt1_p1.a, prt1_p1.c, b, c + Hash Cond: (prt1_p1.a = b) + -> Seq Scan on public.prt1_p1 + Output: prt1_p1.a, prt1_p1.c + Filter: ((prt1_p1.a < 450) AND ((prt1_p1.a % 25) = 0)) + -> Hash + Output: b, c + -> Result + Output: b, c + One-Time Filter: false + -> Hash Full Join + Output: prt1_p2.a, prt1_p2.c, prt2_p2.b, prt2_p2.c + Hash Cond: (prt1_p2.a = prt2_p2.b) + -> Seq Scan on public.prt1_p2 + Output: prt1_p2.a, prt1_p2.c + Filter: ((prt1_p2.a < 450) AND ((prt1_p2.a % 25) = 0)) + -> Hash + Output: prt2_p2.b, prt2_p2.c + -> Seq Scan on public.prt2_p2 + Output: prt2_p2.b, prt2_p2.c + Filter: ((prt2_p2.b > 250) AND ((prt2_p2.b % 25) = 0)) + -> Hash Full Join + Output: a, c, prt2_p3.b, prt2_p3.c + Hash Cond: (prt2_p3.b = a) + -> Seq Scan on public.prt2_p3 + Output: prt2_p3.b, prt2_p3.c + Filter: ((prt2_p3.b > 250) AND ((prt2_p3.b % 25) = 0)) + -> Hash + Output: a, c + -> Result + Output: a, c + One-Time Filter: false +(37 rows) + +SELECT t1.a, t1.c, t2.b, t2.c FROM (SELECT * FROM prt1 WHERE a < 450 AND a % 25 = 0) t1 FULL JOIN (SELECT * FROM prt2 WHERE b > 250 AND b % 25 = 0) t2 ON t1.a = t2.b ORDER BY t1.a, t2.b; + a | c | b | c +-----+------+-----+------ + 0 | 0000 | | + 50 | 0050 | | + 100 | 0100 | | + 150 | 0150 | | + 200 | 0200 | | + 250 | 0250 | | + 300 | 0300 | 300 | 0300 + 350 | 0350 | | + 400 | 0400 | | + | | 375 | 0375 + | | 450 | 0450 + | | 525 | 0525 +(12 rows) + +SELECT t1.a, t1.c, t2.b, t2.c FROM (SELECT * FROM uprt1 WHERE a < 450 AND a % 25 = 0) t1 FULL JOIN (SELECT * FROM uprt2 WHERE b > 250 AND b % 25 = 0) t2 ON t1.a = t2.b ORDER BY t1.a, t2.b; + a | c | b | c +-----+------+-----+------ + 0 | 0000 | | + 50 | 0050 | | + 100 | 0100 | | + 150 | 0150 | | + 200 | 0200 | | + 250 | 0250 | | + 300 | 0300 | 300 | 0300 + 350 | 0350 | | + 400 | 0400 | | + | | 375 | 0375 + | | 450 | 0450 + | | 525 | 0525 +(12 rows) + +-- Semi-join +EXPLAIN (VERBOSE, COSTS OFF) +SELECT t1.* FROM prt1 t1 WHERE t1.a IN (SELECT t1.b FROM prt2 t1 WHERE t1.b % 25 = 0) AND t1.a % 25 = 0 ORDER BY t1.a; + QUERY PLAN +---------------------------------------------------- + Merge Append + Sort Key: t1.a + -> Merge Semi Join + Output: t1.a, t1.b, t1.c + Merge Cond: (t1.a = t1_3.b) + -> Sort + Output: t1.a, t1.b, t1.c + Sort Key: t1.a + -> Seq Scan on public.prt1_p1 t1 + Output: t1.a, t1.b, t1.c + Filter: ((t1.a % 25) = 0) + -> Sort + Output: t1_3.b + Sort Key: t1_3.b + -> Seq Scan on public.prt2_p1 t1_3 + Output: t1_3.b + Filter: ((t1_3.b % 25) = 0) + -> Merge Semi Join + Output: t1_2.a, t1_2.b, t1_2.c + Merge Cond: (t1_2.a = t1_4.b) + -> Sort + Output: t1_2.a, t1_2.b, t1_2.c + Sort Key: t1_2.a + -> Seq Scan on public.prt1_p2 t1_2 + Output: t1_2.a, t1_2.b, t1_2.c + Filter: ((t1_2.a % 25) = 0) + -> Sort + Output: t1_4.b + Sort Key: t1_4.b + -> Seq Scan on public.prt2_p2 t1_4 + Output: t1_4.b + Filter: ((t1_4.b % 25) = 0) + -> Merge Semi Join + Output: t1_1.a, t1_1.b, t1_1.c + Merge Cond: (t1_1.a = t1_5.b) + -> Sort + Output: t1_1.a, t1_1.b, t1_1.c + Sort Key: t1_1.a + -> Seq Scan on public.prt1_p3 t1_1 + Output: t1_1.a, t1_1.b, t1_1.c + Filter: ((t1_1.a % 25) = 0) + -> Sort + Output: t1_5.b + Sort Key: t1_5.b + -> Seq Scan on public.prt2_p3 t1_5 + Output: t1_5.b + Filter: ((t1_5.b % 25) = 0) +(47 rows) + +SELECT t1.* FROM prt1 t1 WHERE t1.a IN (SELECT t1.b FROM prt2 t1 WHERE t1.b % 25 = 0) AND t1.a % 25 = 0 ORDER BY t1.a; + a | b | c +-----+-----+------ + 0 | 0 | 0000 + 150 | 150 | 0150 + 300 | 300 | 0300 + 450 | 450 | 0450 +(4 rows) + +SELECT t1.* FROM uprt1 t1 WHERE t1.a IN (SELECT t1.b FROM uprt2 t1 WHERE t1.b % 25 = 0) AND t1.a % 25 = 0 ORDER BY t1.a; + a | b | c +-----+-----+------ + 0 | 0 | 0000 + 150 | 150 | 0150 + 300 | 300 | 0300 + 450 | 450 | 0450 +(4 rows) + +-- lateral reference +EXPLAIN (VERBOSE, COSTS OFF) +SELECT * FROM prt1 t1 LEFT JOIN LATERAL + (SELECT t2.a AS t2a, t3.a AS t3a, least(t1.a,t2.a,t3.a) FROM prt1 t2 JOIN prt2 t3 ON (t2.a = t3.b)) ss + ON t1.a = ss.t2a WHERE t1.a % 25 = 0 ORDER BY t1.a; + QUERY PLAN +----------------------------------------------------------------------------------------------------- + Sort + Output: t1.a, t1.b, t1.c, t2.a, t3.a, (LEAST(t1.a, t2.a, t3.a)), t1.a + Sort Key: t1.a + -> Result + Output: t1.a, t1.b, t1.c, t2.a, t3.a, (LEAST(t1.a, t2.a, t3.a)), t1.a + -> Append + -> Nested Loop Left Join + Output: t1.a, t1.b, t1.c, t2.a, t3.a, (LEAST(t1.a, t2.a, t3.a)) + -> Seq Scan on public.prt1_p1 t1 + Output: t1.a, t1.b, t1.c + Filter: ((t1.a % 25) = 0) + -> Hash Join + Output: t2.a, t3.a, LEAST(t1.a, t2.a, t3.a) + Hash Cond: (t3.b = t2.a) + -> Seq Scan on public.prt2_p1 t3 + Output: t3.a, t3.b + -> Hash + Output: t2.a + -> Seq Scan on public.prt1_p1 t2 + Output: t2.a + Filter: (t1.a = t2.a) + -> Nested Loop Left Join + Output: t1_2.a, t1_2.b, t1_2.c, t2_2.a, t3_1.a, (LEAST(t1_2.a, t2_2.a, t3_1.a)) + -> Seq Scan on public.prt1_p2 t1_2 + Output: t1_2.a, t1_2.b, t1_2.c + Filter: ((t1_2.a % 25) = 0) + -> Hash Join + Output: t2_2.a, t3_1.a, LEAST(t1_2.a, t2_2.a, t3_1.a) + Hash Cond: (t3_1.b = t2_2.a) + -> Seq Scan on public.prt2_p2 t3_1 + Output: t3_1.a, t3_1.b + -> Hash + Output: t2_2.a + -> Seq Scan on public.prt1_p2 t2_2 + Output: t2_2.a + Filter: (t1_2.a = t2_2.a) + -> Nested Loop Left Join + Output: t1_1.a, t1_1.b, t1_1.c, t2_1.a, t3_2.a, (LEAST(t1_1.a, t2_1.a, t3_2.a)) + -> Seq Scan on public.prt1_p3 t1_1 + Output: t1_1.a, t1_1.b, t1_1.c + Filter: ((t1_1.a % 25) = 0) + -> Hash Join + Output: t2_1.a, t3_2.a, LEAST(t1_1.a, t2_1.a, t3_2.a) + Hash Cond: (t3_2.b = t2_1.a) + -> Seq Scan on public.prt2_p3 t3_2 + Output: t3_2.a, t3_2.b + -> Hash + Output: t2_1.a + -> Seq Scan on public.prt1_p3 t2_1 + Output: t2_1.a + Filter: (t1_1.a = t2_1.a) +(51 rows) + +SELECT * FROM prt1 t1 LEFT JOIN LATERAL + (SELECT t2.a AS t2a, t3.a AS t3a, least(t1.a,t2.a,t3.a) FROM prt1 t2 JOIN prt2 t3 ON (t2.a = t3.b)) ss + ON t1.a = ss.t2a WHERE t1.a % 25 = 0 ORDER BY t1.a; + a | b | c | t2a | t3a | least +-----+-----+------+-----+-----+------- + 0 | 0 | 0000 | 0 | 0 | 0 + 50 | 50 | 0050 | | | + 100 | 100 | 0100 | | | + 150 | 150 | 0150 | 150 | 150 | 150 + 200 | 200 | 0200 | | | + 250 | 250 | 0250 | | | + 300 | 300 | 0300 | 300 | 300 | 300 + 350 | 350 | 0350 | | | + 400 | 400 | 0400 | | | + 450 | 450 | 0450 | 450 | 450 | 450 + 500 | 500 | 0500 | | | + 550 | 550 | 0550 | | | +(12 rows) + +SELECT * FROM uprt1 t1 LEFT JOIN LATERAL + (SELECT t2.a AS t2a, t3.a AS t3a, least(t1.a,t2.a,t3.a) FROM uprt1 t2 JOIN uprt2 t3 ON (t2.a = t3.b)) ss + ON t1.a = ss.t2a WHERE t1.a % 25 = 0 ORDER BY t1.a; + a | b | c | t2a | t3a | least +-----+-----+------+-----+-----+------- + 0 | 0 | 0000 | 0 | 0 | 0 + 50 | 50 | 0050 | | | + 100 | 100 | 0100 | | | + 150 | 150 | 0150 | 150 | 150 | 150 + 200 | 200 | 0200 | | | + 250 | 250 | 0250 | | | + 300 | 300 | 0300 | 300 | 300 | 300 + 350 | 350 | 0350 | | | + 400 | 400 | 0400 | | | + 450 | 450 | 0450 | 450 | 450 | 450 + 500 | 500 | 0500 | | | + 550 | 550 | 0550 | | | +(12 rows) + +EXPLAIN (VERBOSE, COSTS OFF) +SELECT * FROM prt1 t1 LEFT JOIN LATERAL + (SELECT t2.a AS t2a, t3.a AS t3a, least(t1.a,t2.a,t3.a) FROM prt1 t2 JOIN prt2 t3 ON (t2.a = t3.b)) ss + ON t1.b = ss.t2a WHERE t1.a % 25 = 0 ORDER BY t1.a; + QUERY PLAN +------------------------------------------------------------------------------- + Sort + Output: t1.a, t1.b, t1.c, t2.a, t3.a, (LEAST(t1.a, t2.a, t3.a)), t1.a + Sort Key: t1.a + -> Nested Loop Left Join + Output: t1.a, t1.b, t1.c, t2.a, t3.a, (LEAST(t1.a, t2.a, t3.a)), t1.a + -> Append + -> Seq Scan on public.prt1 t1 + Output: t1.a, t1.b, t1.c + Filter: ((t1.a % 25) = 0) + -> Seq Scan on public.prt1_p1 t1_1 + Output: t1_1.a, t1_1.b, t1_1.c + Filter: ((t1_1.a % 25) = 0) + -> Seq Scan on public.prt1_p3 t1_2 + Output: t1_2.a, t1_2.b, t1_2.c + Filter: ((t1_2.a % 25) = 0) + -> Seq Scan on public.prt1_p2 t1_3 + Output: t1_3.a, t1_3.b, t1_3.c + Filter: ((t1_3.a % 25) = 0) + -> Append + -> Hash Join + Output: t2.a, t3.a, LEAST(t1.a, t2.a, t3.a) + Hash Cond: (t3.b = t2.a) + -> Seq Scan on public.prt2_p1 t3 + Output: t3.a, t3.b + -> Hash + Output: t2.a + -> Seq Scan on public.prt1_p1 t2 + Output: t2.a + Filter: (t1.b = t2.a) + -> Hash Join + Output: t2_2.a, t3_1.a, LEAST(t1.a, t2_2.a, t3_1.a) + Hash Cond: (t3_1.b = t2_2.a) + -> Seq Scan on public.prt2_p2 t3_1 + Output: t3_1.a, t3_1.b + -> Hash + Output: t2_2.a + -> Seq Scan on public.prt1_p2 t2_2 + Output: t2_2.a + Filter: (t1.b = t2_2.a) + -> Hash Join + Output: t2_1.a, t3_2.a, LEAST(t1.a, t2_1.a, t3_2.a) + Hash Cond: (t3_2.b = t2_1.a) + -> Seq Scan on public.prt2_p3 t3_2 + Output: t3_2.a, t3_2.b + -> Hash + Output: t2_1.a + -> Seq Scan on public.prt1_p3 t2_1 + Output: t2_1.a + Filter: (t1.b = t2_1.a) +(49 rows) + +SELECT * FROM prt1 t1 LEFT JOIN LATERAL + (SELECT t2.a AS t2a, t3.a AS t3a, least(t1.a,t2.a,t3.a) FROM prt1 t2 JOIN prt2 t3 ON (t2.a = t3.b)) ss + ON t1.b = ss.t2a WHERE t1.a % 25 = 0 ORDER BY t1.a; + a | b | c | t2a | t3a | least +-----+-----+------+-----+-----+------- + 0 | 0 | 0000 | 0 | 0 | 0 + 50 | 50 | 0050 | | | + 100 | 100 | 0100 | | | + 150 | 150 | 0150 | 150 | 150 | 150 + 200 | 200 | 0200 | | | + 250 | 250 | 0250 | | | + 300 | 300 | 0300 | 300 | 300 | 300 + 350 | 350 | 0350 | | | + 400 | 400 | 0400 | | | + 450 | 450 | 0450 | 450 | 450 | 450 + 500 | 500 | 0500 | | | + 550 | 550 | 0550 | | | +(12 rows) + +SELECT * FROM uprt1 t1 LEFT JOIN LATERAL + (SELECT t2.a AS t2a, t3.a AS t3a, least(t1.a,t2.a,t3.a) FROM uprt1 t2 JOIN uprt2 t3 ON (t2.a = t3.b)) ss + ON t1.b = ss.t2a WHERE t1.a % 25 = 0 ORDER BY t1.a; + a | b | c | t2a | t3a | least +-----+-----+------+-----+-----+------- + 0 | 0 | 0000 | 0 | 0 | 0 + 50 | 50 | 0050 | | | + 100 | 100 | 0100 | | | + 150 | 150 | 0150 | 150 | 150 | 150 + 200 | 200 | 0200 | | | + 250 | 250 | 0250 | | | + 300 | 300 | 0300 | 300 | 300 | 300 + 350 | 350 | 0350 | | | + 400 | 400 | 0400 | | | + 450 | 450 | 0450 | 450 | 450 | 450 + 500 | 500 | 0500 | | | + 550 | 550 | 0550 | | | +(12 rows) + +-- +-- partitioned by expression +-- +CREATE TABLE prt1_e (a int, b int, c varchar) PARTITION BY RANGE(((a + b)/2)); +CREATE TABLE prt1_e_p1 PARTITION OF prt1_e FOR VALUES FROM (0) TO (250); +CREATE TABLE prt1_e_p2 PARTITION OF prt1_e FOR VALUES FROM (250) TO (500); +CREATE TABLE prt1_e_p3 PARTITION OF prt1_e FOR VALUES FROM (500) TO (600); +INSERT INTO prt1_e SELECT i, i, to_char(i, 'FM0000') FROM generate_series(0, 599, 2) i; +ANALYZE prt1_e; +ANALYZE prt1_e_p1; +ANALYZE prt1_e_p2; +ANALYZE prt1_e_p3; +-- TODO: This table is created only for testing the results. Remove once +-- results are tested. +CREATE TABLE uprt1_e AS SELECT * FROM prt1_e; +CREATE TABLE prt2_e (a int, b int, c varchar) PARTITION BY RANGE(((b + a)/2)); +CREATE TABLE prt2_e_p1 PARTITION OF prt2_e FOR VALUES FROM (0) TO (250); +CREATE TABLE prt2_e_p2 PARTITION OF prt2_e FOR VALUES FROM (250) TO (500); +CREATE TABLE prt2_e_p3 PARTITION OF prt2_e FOR VALUES FROM (500) TO (600); +INSERT INTO prt2_e SELECT i, i, to_char(i, 'FM0000') FROM generate_series(0, 599, 3) i; +ANALYZE prt2_e; +ANALYZE prt2_e_p1; +ANALYZE prt2_e_p2; +ANALYZE prt2_e_p3; +-- TODO: This table is created only for testing the results. Remove once +-- results are tested. +CREATE TABLE uprt2_e AS SELECT * FROM prt2_e; +EXPLAIN (VERBOSE, COSTS OFF) +SELECT t1.a, t1.c, t2.b, t2.c FROM prt1_e t1, prt2_e t2 WHERE (t1.a + t1.b)/2 = (t2.b + t2.a)/2 AND t1.a % 25 = 0 ORDER BY t1.a, t2.b; + QUERY PLAN +------------------------------------------------------------------------------ + Sort + Output: t1.a, t1.c, t2.b, t2.c + Sort Key: t1.a, t2.b + -> Append + -> Hash Join + Output: t1.a, t1.c, t2.b, t2.c + Hash Cond: (((t2.b + t2.a) / 2) = ((t1.a + t1.b) / 2)) + -> Seq Scan on public.prt2_e_p1 t2 + Output: t2.b, t2.c, t2.a + -> Hash + Output: t1.a, t1.c, t1.b + -> Seq Scan on public.prt1_e_p1 t1 + Output: t1.a, t1.c, t1.b + Filter: ((t1.a % 25) = 0) + -> Hash Join + Output: t1_1.a, t1_1.c, t2_1.b, t2_1.c + Hash Cond: (((t2_1.b + t2_1.a) / 2) = ((t1_1.a + t1_1.b) / 2)) + -> Seq Scan on public.prt2_e_p2 t2_1 + Output: t2_1.b, t2_1.c, t2_1.a + -> Hash + Output: t1_1.a, t1_1.c, t1_1.b + -> Seq Scan on public.prt1_e_p2 t1_1 + Output: t1_1.a, t1_1.c, t1_1.b + Filter: ((t1_1.a % 25) = 0) + -> Hash Join + Output: t1_2.a, t1_2.c, t2_2.b, t2_2.c + Hash Cond: (((t2_2.b + t2_2.a) / 2) = ((t1_2.a + t1_2.b) / 2)) + -> Seq Scan on public.prt2_e_p3 t2_2 + Output: t2_2.b, t2_2.c, t2_2.a + -> Hash + Output: t1_2.a, t1_2.c, t1_2.b + -> Seq Scan on public.prt1_e_p3 t1_2 + Output: t1_2.a, t1_2.c, t1_2.b + Filter: ((t1_2.a % 25) = 0) +(34 rows) + +SELECT t1.a, t1.c, t2.b, t2.c FROM prt1_e t1, prt2_e t2 WHERE (t1.a + t1.b)/2 = (t2.b + t2.a)/2 AND t1.a % 25 = 0 ORDER BY t1.a, t2.b; + a | c | b | c +-----+------+-----+------ + 0 | 0000 | 0 | 0000 + 150 | 0150 | 150 | 0150 + 300 | 0300 | 300 | 0300 + 450 | 0450 | 450 | 0450 +(4 rows) + +SELECT t1.a, t1.c, t2.b, t2.c FROM uprt1_e t1, uprt2_e t2 WHERE (t1.a + t1.b)/2 = (t2.b + t2.a)/2 AND t1.a % 25 = 0 ORDER BY t1.a, t2.b; + a | c | b | c +-----+------+-----+------ + 0 | 0000 | 0 | 0000 + 150 | 0150 | 150 | 0150 + 300 | 0300 | 300 | 0300 + 450 | 0450 | 450 | 0450 +(4 rows) + +EXPLAIN (VERBOSE, COSTS OFF) +SELECT t1.a, t1.c, t2.b, t2.c FROM prt1_e t1 LEFT JOIN prt2_e t2 ON (t1.a + t1.b)/2 = (t2.b + t2.a)/2 WHERE t1.a % 25 = 0 ORDER BY t1.a, t2.b; + QUERY PLAN +------------------------------------------------------------------------------ + Sort + Output: t1.a, t1.c, t2.b, t2.c + Sort Key: t1.a, t2.b + -> Append + -> Hash Right Join + Output: t1.a, t1.c, t2.b, t2.c + Hash Cond: (((t2.b + t2.a) / 2) = ((t1.a + t1.b) / 2)) + -> Seq Scan on public.prt2_e_p1 t2 + Output: t2.b, t2.c, t2.a + -> Hash + Output: t1.a, t1.c, t1.b + -> Seq Scan on public.prt1_e_p1 t1 + Output: t1.a, t1.c, t1.b + Filter: ((t1.a % 25) = 0) + -> Hash Right Join + Output: t1_1.a, t1_1.c, t2_1.b, t2_1.c + Hash Cond: (((t2_1.b + t2_1.a) / 2) = ((t1_1.a + t1_1.b) / 2)) + -> Seq Scan on public.prt2_e_p2 t2_1 + Output: t2_1.b, t2_1.c, t2_1.a + -> Hash + Output: t1_1.a, t1_1.c, t1_1.b + -> Seq Scan on public.prt1_e_p2 t1_1 + Output: t1_1.a, t1_1.c, t1_1.b + Filter: ((t1_1.a % 25) = 0) + -> Hash Right Join + Output: t1_2.a, t1_2.c, t2_2.b, t2_2.c + Hash Cond: (((t2_2.b + t2_2.a) / 2) = ((t1_2.a + t1_2.b) / 2)) + -> Seq Scan on public.prt2_e_p3 t2_2 + Output: t2_2.b, t2_2.c, t2_2.a + -> Hash + Output: t1_2.a, t1_2.c, t1_2.b + -> Seq Scan on public.prt1_e_p3 t1_2 + Output: t1_2.a, t1_2.c, t1_2.b + Filter: ((t1_2.a % 25) = 0) +(34 rows) + +SELECT t1.a, t1.c, t2.b, t2.c FROM prt1_e t1 LEFT JOIN prt2_e t2 ON (t1.a + t1.b)/2 = (t2.b + t2.a)/2 WHERE t1.a % 25 = 0 ORDER BY t1.a, t2.b; + a | c | b | c +-----+------+-----+------ + 0 | 0000 | 0 | 0000 + 50 | 0050 | | + 100 | 0100 | | + 150 | 0150 | 150 | 0150 + 200 | 0200 | | + 250 | 0250 | | + 300 | 0300 | 300 | 0300 + 350 | 0350 | | + 400 | 0400 | | + 450 | 0450 | 450 | 0450 + 500 | 0500 | | + 550 | 0550 | | +(12 rows) + +SELECT t1.a, t1.c, t2.b, t2.c FROM uprt1_e t1 LEFT JOIN uprt2_e t2 ON (t1.a + t1.b)/2 = (t2.b + t2.a)/2 WHERE t1.a % 25 = 0 ORDER BY t1.a, t2.b; + a | c | b | c +-----+------+-----+------ + 0 | 0000 | 0 | 0000 + 50 | 0050 | | + 100 | 0100 | | + 150 | 0150 | 150 | 0150 + 200 | 0200 | | + 250 | 0250 | | + 300 | 0300 | 300 | 0300 + 350 | 0350 | | + 400 | 0400 | | + 450 | 0450 | 450 | 0450 + 500 | 0500 | | + 550 | 0550 | | +(12 rows) + +-- +-- N-way join +-- +EXPLAIN (VERBOSE, COSTS OFF) +SELECT t1.a, t1.c, t2.b, t2.c, t3.a + t3.b, t3.c FROM prt1 t1, prt2 t2, prt1_e t3 WHERE t1.a = t2.b AND t1.a = (t3.a + t3.b)/2 AND t1.a % 25 = 0 ORDER BY t1.a, t2.b; + QUERY PLAN +------------------------------------------------------------------------------------ + Sort + Output: t1.a, t1.c, t2.b, t2.c, ((t3.a + t3.b)), t3.c + Sort Key: t1.a + -> Result + Output: t1.a, t1.c, t2.b, t2.c, (t3.a + t3.b), t3.c + -> Append + -> Hash Join + Output: t1.a, t1.c, t2.b, t2.c, t3.a, t3.b, t3.c + Hash Cond: (((t3.a + t3.b) / 2) = t1.a) + -> Seq Scan on public.prt1_e_p1 t3 + Output: t3.a, t3.b, t3.c + -> Hash + Output: t1.a, t1.c, t2.b, t2.c + -> Hash Join + Output: t1.a, t1.c, t2.b, t2.c + Hash Cond: (t2.b = t1.a) + -> Seq Scan on public.prt2_p1 t2 + Output: t2.b, t2.c + -> Hash + Output: t1.a, t1.c + -> Seq Scan on public.prt1_p1 t1 + Output: t1.a, t1.c + Filter: ((t1.a % 25) = 0) + -> Hash Join + Output: t1_2.a, t1_2.c, t2_1.b, t2_1.c, t3_1.a, t3_1.b, t3_1.c + Hash Cond: (((t3_1.a + t3_1.b) / 2) = t1_2.a) + -> Seq Scan on public.prt1_e_p2 t3_1 + Output: t3_1.a, t3_1.b, t3_1.c + -> Hash + Output: t1_2.a, t1_2.c, t2_1.b, t2_1.c + -> Hash Join + Output: t1_2.a, t1_2.c, t2_1.b, t2_1.c + Hash Cond: (t2_1.b = t1_2.a) + -> Seq Scan on public.prt2_p2 t2_1 + Output: t2_1.b, t2_1.c + -> Hash + Output: t1_2.a, t1_2.c + -> Seq Scan on public.prt1_p2 t1_2 + Output: t1_2.a, t1_2.c + Filter: ((t1_2.a % 25) = 0) + -> Hash Join + Output: t1_1.a, t1_1.c, t2_2.b, t2_2.c, t3_2.a, t3_2.b, t3_2.c + Hash Cond: (((t3_2.a + t3_2.b) / 2) = t1_1.a) + -> Seq Scan on public.prt1_e_p3 t3_2 + Output: t3_2.a, t3_2.b, t3_2.c + -> Hash + Output: t1_1.a, t1_1.c, t2_2.b, t2_2.c + -> Hash Join + Output: t1_1.a, t1_1.c, t2_2.b, t2_2.c + Hash Cond: (t2_2.b = t1_1.a) + -> Seq Scan on public.prt2_p3 t2_2 + Output: t2_2.b, t2_2.c + -> Hash + Output: t1_1.a, t1_1.c + -> Seq Scan on public.prt1_p3 t1_1 + Output: t1_1.a, t1_1.c + Filter: ((t1_1.a % 25) = 0) +(57 rows) + +SELECT t1.a, t1.c, t2.b, t2.c, t3.a + t3.b, t3.c FROM prt1 t1, prt2 t2, prt1_e t3 WHERE t1.a = t2.b AND t1.a = (t3.a + t3.b)/2 AND t1.a % 25 = 0 ORDER BY t1.a, t2.b; + a | c | b | c | ?column? | c +-----+------+-----+------+----------+------ + 0 | 0000 | 0 | 0000 | 0 | 0000 + 150 | 0150 | 150 | 0150 | 300 | 0150 + 300 | 0300 | 300 | 0300 | 600 | 0300 + 450 | 0450 | 450 | 0450 | 900 | 0450 +(4 rows) + +SELECT t1.a, t1.c, t2.b, t2.c, t3.a + t3.b, t3.c FROM uprt1 t1, uprt2 t2, uprt1_e t3 WHERE t1.a = t2.b AND t1.a = (t3.a + t3.b)/2 AND t1.a % 25 = 0 ORDER BY t1.a, t2.b; + a | c | b | c | ?column? | c +-----+------+-----+------+----------+------ + 0 | 0000 | 0 | 0000 | 0 | 0000 + 150 | 0150 | 150 | 0150 | 300 | 0150 + 300 | 0300 | 300 | 0300 | 600 | 0300 + 450 | 0450 | 450 | 0450 | 900 | 0450 +(4 rows) + +EXPLAIN (VERBOSE, COSTS OFF) +SELECT t1.a, t1.c, t2.b, t2.c, t3.a + t3.b, t3.c FROM (prt1 t1 LEFT JOIN prt2 t2 ON t1.a = t2.b) LEFT JOIN prt1_e t3 ON (t1.a = (t3.a + t3.b)/2) WHERE t1.a % 25 = 0 ORDER BY t1.a, t2.b, t3.a + t3.b; + QUERY PLAN +------------------------------------------------------------------------------------ + Sort + Output: t1.a, t1.c, t2.b, t2.c, ((t3.a + t3.b)), t3.c + Sort Key: t1.a, t2.b, ((t3.a + t3.b)) + -> Result + Output: t1.a, t1.c, t2.b, t2.c, (t3.a + t3.b), t3.c + -> Append + -> Hash Right Join + Output: t1.a, t1.c, t2.b, t2.c, t3.a, t3.b, t3.c + Hash Cond: (((t3.a + t3.b) / 2) = t1.a) + -> Seq Scan on public.prt1_e_p1 t3 + Output: t3.a, t3.b, t3.c + -> Hash + Output: t1.a, t1.c, t2.b, t2.c + -> Hash Right Join + Output: t1.a, t1.c, t2.b, t2.c + Hash Cond: (t2.b = t1.a) + -> Seq Scan on public.prt2_p1 t2 + Output: t2.b, t2.c + -> Hash + Output: t1.a, t1.c + -> Seq Scan on public.prt1_p1 t1 + Output: t1.a, t1.c + Filter: ((t1.a % 25) = 0) + -> Hash Right Join + Output: t1_2.a, t1_2.c, t2_1.b, t2_1.c, t3_1.a, t3_1.b, t3_1.c + Hash Cond: (((t3_1.a + t3_1.b) / 2) = t1_2.a) + -> Seq Scan on public.prt1_e_p2 t3_1 + Output: t3_1.a, t3_1.b, t3_1.c + -> Hash + Output: t1_2.a, t1_2.c, t2_1.b, t2_1.c + -> Hash Right Join + Output: t1_2.a, t1_2.c, t2_1.b, t2_1.c + Hash Cond: (t2_1.b = t1_2.a) + -> Seq Scan on public.prt2_p2 t2_1 + Output: t2_1.b, t2_1.c + -> Hash + Output: t1_2.a, t1_2.c + -> Seq Scan on public.prt1_p2 t1_2 + Output: t1_2.a, t1_2.c + Filter: ((t1_2.a % 25) = 0) + -> Hash Right Join + Output: t1_1.a, t1_1.c, t2_2.b, t2_2.c, t3_2.a, t3_2.b, t3_2.c + Hash Cond: (((t3_2.a + t3_2.b) / 2) = t1_1.a) + -> Seq Scan on public.prt1_e_p3 t3_2 + Output: t3_2.a, t3_2.b, t3_2.c + -> Hash + Output: t1_1.a, t1_1.c, t2_2.b, t2_2.c + -> Hash Right Join + Output: t1_1.a, t1_1.c, t2_2.b, t2_2.c + Hash Cond: (t2_2.b = t1_1.a) + -> Seq Scan on public.prt2_p3 t2_2 + Output: t2_2.b, t2_2.c + -> Hash + Output: t1_1.a, t1_1.c + -> Seq Scan on public.prt1_p3 t1_1 + Output: t1_1.a, t1_1.c + Filter: ((t1_1.a % 25) = 0) +(57 rows) + +SELECT t1.a, t1.c, t2.b, t2.c, t3.a + t3.b, t3.c FROM (prt1 t1 LEFT JOIN prt2 t2 ON t1.a = t2.b) LEFT JOIN prt1_e t3 ON (t1.a = (t3.a + t3.b)/2) WHERE t1.a % 25 = 0 ORDER BY t1.a, t2.b, t3.a + t3.b; + a | c | b | c | ?column? | c +-----+------+-----+------+----------+------ + 0 | 0000 | 0 | 0000 | 0 | 0000 + 50 | 0050 | | | 100 | 0050 + 100 | 0100 | | | 200 | 0100 + 150 | 0150 | 150 | 0150 | 300 | 0150 + 200 | 0200 | | | 400 | 0200 + 250 | 0250 | | | 500 | 0250 + 300 | 0300 | 300 | 0300 | 600 | 0300 + 350 | 0350 | | | 700 | 0350 + 400 | 0400 | | | 800 | 0400 + 450 | 0450 | 450 | 0450 | 900 | 0450 + 500 | 0500 | | | 1000 | 0500 + 550 | 0550 | | | 1100 | 0550 +(12 rows) + +SELECT t1.a, t1.c, t2.b, t2.c, t3.a + t3.b, t3.c FROM (uprt1 t1 LEFT JOIN uprt2 t2 ON t1.a = t2.b) LEFT JOIN uprt1_e t3 ON (t1.a = (t3.a + t3.b)/2) WHERE t1.a % 25 = 0 ORDER BY t1.a, t2.b, t3.a + t3.b; + a | c | b | c | ?column? | c +-----+------+-----+------+----------+------ + 0 | 0000 | 0 | 0000 | 0 | 0000 + 50 | 0050 | | | 100 | 0050 + 100 | 0100 | | | 200 | 0100 + 150 | 0150 | 150 | 0150 | 300 | 0150 + 200 | 0200 | | | 400 | 0200 + 250 | 0250 | | | 500 | 0250 + 300 | 0300 | 300 | 0300 | 600 | 0300 + 350 | 0350 | | | 700 | 0350 + 400 | 0400 | | | 800 | 0400 + 450 | 0450 | 450 | 0450 | 900 | 0450 + 500 | 0500 | | | 1000 | 0500 + 550 | 0550 | | | 1100 | 0550 +(12 rows) + +EXPLAIN (VERBOSE, COSTS OFF) +SELECT t1.a, t1.c, t2.b, t2.c, t3.a + t3.b, t3.c FROM (prt1 t1 LEFT JOIN prt2 t2 ON t1.a = t2.b) LEFT JOIN prt1_e t3 ON (t2.b = (t3.a + t3.b)/2) WHERE t1.a % 25 = 0 ORDER BY t1.a, t2.b, t3.a + t3.b; + QUERY PLAN +------------------------------------------------------------------------------------ + Sort + Output: t1.a, t1.c, t2.b, t2.c, ((t3.a + t3.b)), t3.c + Sort Key: t1.a, t2.b, ((t3.a + t3.b)) + -> Result + Output: t1.a, t1.c, t2.b, t2.c, (t3.a + t3.b), t3.c + -> Append + -> Hash Right Join + Output: t1.a, t1.c, t2.b, t2.c, t3.a, t3.b, t3.c + Hash Cond: (((t3.a + t3.b) / 2) = t2.b) + -> Seq Scan on public.prt1_e_p1 t3 + Output: t3.a, t3.b, t3.c + -> Hash + Output: t1.a, t1.c, t2.b, t2.c + -> Hash Right Join + Output: t1.a, t1.c, t2.b, t2.c + Hash Cond: (t2.b = t1.a) + -> Seq Scan on public.prt2_p1 t2 + Output: t2.b, t2.c + -> Hash + Output: t1.a, t1.c + -> Seq Scan on public.prt1_p1 t1 + Output: t1.a, t1.c + Filter: ((t1.a % 25) = 0) + -> Hash Right Join + Output: t1_2.a, t1_2.c, t2_1.b, t2_1.c, t3_1.a, t3_1.b, t3_1.c + Hash Cond: (((t3_1.a + t3_1.b) / 2) = t2_1.b) + -> Seq Scan on public.prt1_e_p2 t3_1 + Output: t3_1.a, t3_1.b, t3_1.c + -> Hash + Output: t1_2.a, t1_2.c, t2_1.b, t2_1.c + -> Hash Right Join + Output: t1_2.a, t1_2.c, t2_1.b, t2_1.c + Hash Cond: (t2_1.b = t1_2.a) + -> Seq Scan on public.prt2_p2 t2_1 + Output: t2_1.b, t2_1.c + -> Hash + Output: t1_2.a, t1_2.c + -> Seq Scan on public.prt1_p2 t1_2 + Output: t1_2.a, t1_2.c + Filter: ((t1_2.a % 25) = 0) + -> Hash Right Join + Output: t1_1.a, t1_1.c, t2_2.b, t2_2.c, t3_2.a, t3_2.b, t3_2.c + Hash Cond: (((t3_2.a + t3_2.b) / 2) = t2_2.b) + -> Seq Scan on public.prt1_e_p3 t3_2 + Output: t3_2.a, t3_2.b, t3_2.c + -> Hash + Output: t1_1.a, t1_1.c, t2_2.b, t2_2.c + -> Hash Right Join + Output: t1_1.a, t1_1.c, t2_2.b, t2_2.c + Hash Cond: (t2_2.b = t1_1.a) + -> Seq Scan on public.prt2_p3 t2_2 + Output: t2_2.b, t2_2.c + -> Hash + Output: t1_1.a, t1_1.c + -> Seq Scan on public.prt1_p3 t1_1 + Output: t1_1.a, t1_1.c + Filter: ((t1_1.a % 25) = 0) +(57 rows) + +SELECT t1.a, t1.c, t2.b, t2.c, t3.a + t3.b, t3.c FROM (prt1 t1 LEFT JOIN prt2 t2 ON t1.a = t2.b) LEFT JOIN prt1_e t3 ON (t2.b = (t3.a + t3.b)/2) WHERE t1.a % 25 = 0 ORDER BY t1.a, t2.b, t3.a + t3.b; + a | c | b | c | ?column? | c +-----+------+-----+------+----------+------ + 0 | 0000 | 0 | 0000 | 0 | 0000 + 50 | 0050 | | | | + 100 | 0100 | | | | + 150 | 0150 | 150 | 0150 | 300 | 0150 + 200 | 0200 | | | | + 250 | 0250 | | | | + 300 | 0300 | 300 | 0300 | 600 | 0300 + 350 | 0350 | | | | + 400 | 0400 | | | | + 450 | 0450 | 450 | 0450 | 900 | 0450 + 500 | 0500 | | | | + 550 | 0550 | | | | +(12 rows) + +SELECT t1.a, t1.c, t2.b, t2.c, t3.a + t3.b, t3.c FROM (uprt1 t1 LEFT JOIN uprt2 t2 ON t1.a = t2.b) LEFT JOIN uprt1_e t3 ON (t2.b = (t3.a + t3.b)/2) WHERE t1.a % 25 = 0 ORDER BY t1.a, t2.b, t3.a + t3.b; + a | c | b | c | ?column? | c +-----+------+-----+------+----------+------ + 0 | 0000 | 0 | 0000 | 0 | 0000 + 50 | 0050 | | | | + 100 | 0100 | | | | + 150 | 0150 | 150 | 0150 | 300 | 0150 + 200 | 0200 | | | | + 250 | 0250 | | | | + 300 | 0300 | 300 | 0300 | 600 | 0300 + 350 | 0350 | | | | + 400 | 0400 | | | | + 450 | 0450 | 450 | 0450 | 900 | 0450 + 500 | 0500 | | | | + 550 | 0550 | | | | +(12 rows) + +EXPLAIN (VERBOSE, COSTS OFF) +SELECT t1.a, t1.c, t2.b, t2.c, t3.a + t3.b, t3.c FROM (prt1 t1 LEFT JOIN prt2 t2 ON t1.a = t2.b) RIGHT JOIN prt1_e t3 ON (t1.a = (t3.a + t3.b)/2) WHERE t3.a % 25 = 0 ORDER BY t1.a, t2.b, t3.a + t3.b; + QUERY PLAN +------------------------------------------------------------------------------------ + Sort + Output: t1.a, t1.c, t2.b, t2.c, ((t3.a + t3.b)), t3.c + Sort Key: t1.a, t2.b, ((t3.a + t3.b)) + -> Result + Output: t1.a, t1.c, t2.b, t2.c, (t3.a + t3.b), t3.c + -> Append + -> Hash Right Join + Output: t3.a, t3.b, t3.c, t1.a, t1.c, t2.b, t2.c + Hash Cond: (t2.b = t1.a) + -> Seq Scan on public.prt2_p1 t2 + Output: t2.b, t2.c + -> Hash + Output: t3.a, t3.b, t3.c, t1.a, t1.c + -> Hash Right Join + Output: t3.a, t3.b, t3.c, t1.a, t1.c + Hash Cond: (t1.a = ((t3.a + t3.b) / 2)) + -> Seq Scan on public.prt1_p1 t1 + Output: t1.a, t1.c + -> Hash + Output: t3.a, t3.b, t3.c + -> Seq Scan on public.prt1_e_p1 t3 + Output: t3.a, t3.b, t3.c + Filter: ((t3.a % 25) = 0) + -> Hash Right Join + Output: t3_1.a, t3_1.b, t3_1.c, t1_2.a, t1_2.c, t2_1.b, t2_1.c + Hash Cond: (t2_1.b = t1_2.a) + -> Seq Scan on public.prt2_p2 t2_1 + Output: t2_1.b, t2_1.c + -> Hash + Output: t3_1.a, t3_1.b, t3_1.c, t1_2.a, t1_2.c + -> Hash Right Join + Output: t3_1.a, t3_1.b, t3_1.c, t1_2.a, t1_2.c + Hash Cond: (t1_2.a = ((t3_1.a + t3_1.b) / 2)) + -> Seq Scan on public.prt1_p2 t1_2 + Output: t1_2.a, t1_2.c + -> Hash + Output: t3_1.a, t3_1.b, t3_1.c + -> Seq Scan on public.prt1_e_p2 t3_1 + Output: t3_1.a, t3_1.b, t3_1.c + Filter: ((t3_1.a % 25) = 0) + -> Hash Right Join + Output: t3_2.a, t3_2.b, t3_2.c, t1_1.a, t1_1.c, t2_2.b, t2_2.c + Hash Cond: (t2_2.b = t1_1.a) + -> Seq Scan on public.prt2_p3 t2_2 + Output: t2_2.b, t2_2.c + -> Hash + Output: t3_2.a, t3_2.b, t3_2.c, t1_1.a, t1_1.c + -> Hash Right Join + Output: t3_2.a, t3_2.b, t3_2.c, t1_1.a, t1_1.c + Hash Cond: (t1_1.a = ((t3_2.a + t3_2.b) / 2)) + -> Seq Scan on public.prt1_p3 t1_1 + Output: t1_1.a, t1_1.c + -> Hash + Output: t3_2.a, t3_2.b, t3_2.c + -> Seq Scan on public.prt1_e_p3 t3_2 + Output: t3_2.a, t3_2.b, t3_2.c + Filter: ((t3_2.a % 25) = 0) +(57 rows) + +SELECT t1.a, t1.c, t2.b, t2.c, t3.a + t3.b, t3.c FROM (prt1 t1 LEFT JOIN prt2 t2 ON t1.a = t2.b) RIGHT JOIN prt1_e t3 ON (t1.a = (t3.a + t3.b)/2) WHERE t3.a % 25 = 0 ORDER BY t1.a, t2.b, t3.a + t3.b; + a | c | b | c | ?column? | c +-----+------+-----+------+----------+------ + 0 | 0000 | 0 | 0000 | 0 | 0000 + 50 | 0050 | | | 100 | 0050 + 100 | 0100 | | | 200 | 0100 + 150 | 0150 | 150 | 0150 | 300 | 0150 + 200 | 0200 | | | 400 | 0200 + 250 | 0250 | | | 500 | 0250 + 300 | 0300 | 300 | 0300 | 600 | 0300 + 350 | 0350 | | | 700 | 0350 + 400 | 0400 | | | 800 | 0400 + 450 | 0450 | 450 | 0450 | 900 | 0450 + 500 | 0500 | | | 1000 | 0500 + 550 | 0550 | | | 1100 | 0550 +(12 rows) + +SELECT t1.a, t1.c, t2.b, t2.c, t3.a + t3.b, t3.c FROM (uprt1 t1 LEFT JOIN uprt2 t2 ON t1.a = t2.b) RIGHT JOIN uprt1_e t3 ON (t1.a = (t3.a + t3.b)/2) WHERE t3.a % 25 = 0 ORDER BY t1.a, t2.b, t3.a + t3.b; + a | c | b | c | ?column? | c +-----+------+-----+------+----------+------ + 0 | 0000 | 0 | 0000 | 0 | 0000 + 50 | 0050 | | | 100 | 0050 + 100 | 0100 | | | 200 | 0100 + 150 | 0150 | 150 | 0150 | 300 | 0150 + 200 | 0200 | | | 400 | 0200 + 250 | 0250 | | | 500 | 0250 + 300 | 0300 | 300 | 0300 | 600 | 0300 + 350 | 0350 | | | 700 | 0350 + 400 | 0400 | | | 800 | 0400 + 450 | 0450 | 450 | 0450 | 900 | 0450 + 500 | 0500 | | | 1000 | 0500 + 550 | 0550 | | | 1100 | 0550 +(12 rows) + +EXPLAIN (VERBOSE, COSTS OFF) +SELECT t1.a, t1.c, t2.b, t2.c, t3.a + t3.b, t3.c FROM (prt1 t1 RIGHT JOIN prt2 t2 ON t1.a = t2.b) RIGHT JOIN prt1_e t3 ON (t2.b = (t3.a + t3.b)/2) WHERE t3.a % 25 = 0 ORDER BY t1.a, t2.b, t3.a + t3.b; + QUERY PLAN +------------------------------------------------------------------------------------ + Sort + Output: t1.a, t1.c, t2.b, t2.c, ((t3.a + t3.b)), t3.c + Sort Key: t1.a, t2.b, ((t3.a + t3.b)) + -> Result + Output: t1.a, t1.c, t2.b, t2.c, (t3.a + t3.b), t3.c + -> Append + -> Hash Right Join + Output: t3.a, t3.b, t3.c, t2.b, t2.c, t1.a, t1.c + Hash Cond: (t1.a = t2.b) + -> Seq Scan on public.prt1_p1 t1 + Output: t1.a, t1.c + -> Hash + Output: t3.a, t3.b, t3.c, t2.b, t2.c + -> Hash Right Join + Output: t3.a, t3.b, t3.c, t2.b, t2.c + Hash Cond: (t2.b = ((t3.a + t3.b) / 2)) + -> Seq Scan on public.prt2_p1 t2 + Output: t2.b, t2.c + -> Hash + Output: t3.a, t3.b, t3.c + -> Seq Scan on public.prt1_e_p1 t3 + Output: t3.a, t3.b, t3.c + Filter: ((t3.a % 25) = 0) + -> Hash Right Join + Output: t3_1.a, t3_1.b, t3_1.c, t2_1.b, t2_1.c, t1_2.a, t1_2.c + Hash Cond: (t1_2.a = t2_1.b) + -> Seq Scan on public.prt1_p2 t1_2 + Output: t1_2.a, t1_2.c + -> Hash + Output: t3_1.a, t3_1.b, t3_1.c, t2_1.b, t2_1.c + -> Hash Right Join + Output: t3_1.a, t3_1.b, t3_1.c, t2_1.b, t2_1.c + Hash Cond: (t2_1.b = ((t3_1.a + t3_1.b) / 2)) + -> Seq Scan on public.prt2_p2 t2_1 + Output: t2_1.b, t2_1.c + -> Hash + Output: t3_1.a, t3_1.b, t3_1.c + -> Seq Scan on public.prt1_e_p2 t3_1 + Output: t3_1.a, t3_1.b, t3_1.c + Filter: ((t3_1.a % 25) = 0) + -> Hash Right Join + Output: t3_2.a, t3_2.b, t3_2.c, t2_2.b, t2_2.c, t1_1.a, t1_1.c + Hash Cond: (t1_1.a = t2_2.b) + -> Seq Scan on public.prt1_p3 t1_1 + Output: t1_1.a, t1_1.c + -> Hash + Output: t3_2.a, t3_2.b, t3_2.c, t2_2.b, t2_2.c + -> Hash Right Join + Output: t3_2.a, t3_2.b, t3_2.c, t2_2.b, t2_2.c + Hash Cond: (t2_2.b = ((t3_2.a + t3_2.b) / 2)) + -> Seq Scan on public.prt2_p3 t2_2 + Output: t2_2.b, t2_2.c + -> Hash + Output: t3_2.a, t3_2.b, t3_2.c + -> Seq Scan on public.prt1_e_p3 t3_2 + Output: t3_2.a, t3_2.b, t3_2.c + Filter: ((t3_2.a % 25) = 0) +(57 rows) + +SELECT t1.a, t1.c, t2.b, t2.c, t3.a + t3.b, t3.c FROM (prt1 t1 RIGHT JOIN prt2 t2 ON t1.a = t2.b) RIGHT JOIN prt1_e t3 ON (t2.b = (t3.a + t3.b)/2) WHERE t3.a % 25 = 0 ORDER BY t1.a, t2.b, t3.a + t3.b; + a | c | b | c | ?column? | c +-----+------+-----+------+----------+------ + 0 | 0000 | 0 | 0000 | 0 | 0000 + 150 | 0150 | 150 | 0150 | 300 | 0150 + 300 | 0300 | 300 | 0300 | 600 | 0300 + 450 | 0450 | 450 | 0450 | 900 | 0450 + | | | | 100 | 0050 + | | | | 200 | 0100 + | | | | 400 | 0200 + | | | | 500 | 0250 + | | | | 700 | 0350 + | | | | 800 | 0400 + | | | | 1000 | 0500 + | | | | 1100 | 0550 +(12 rows) + +SELECT t1.a, t1.c, t2.b, t2.c, t3.a + t3.b, t3.c FROM (uprt1 t1 RIGHT JOIN uprt2 t2 ON t1.a = t2.b) RIGHT JOIN uprt1_e t3 ON (t2.b = (t3.a + t3.b)/2) WHERE t3.a % 25 = 0 ORDER BY t1.a, t2.b, t3.a + t3.b; + a | c | b | c | ?column? | c +-----+------+-----+------+----------+------ + 0 | 0000 | 0 | 0000 | 0 | 0000 + 150 | 0150 | 150 | 0150 | 300 | 0150 + 300 | 0300 | 300 | 0300 | 600 | 0300 + 450 | 0450 | 450 | 0450 | 900 | 0450 + | | | | 100 | 0050 + | | | | 200 | 0100 + | | | | 400 | 0200 + | | | | 500 | 0250 + | | | | 700 | 0350 + | | | | 800 | 0400 + | | | | 1000 | 0500 + | | | | 1100 | 0550 +(12 rows) + +EXPLAIN (VERBOSE, COSTS OFF) +SELECT t1.a, t1.c, t2.b, t2.c, t3.a + t3.b, t3.c FROM ((SELECT * FROM prt1 WHERE prt1.a % 25 = 0) t1 FULL JOIN (SELECT * FROM prt2 WHERE prt2.b % 25 = 0) t2 ON (t1.a = t2.b)) FULL JOIN (SELECT * FROM prt1_e WHERE prt1_e.a % 25 = 0) t3 ON (t1.a = (t3.a + t3.b)/2) ORDER BY t1.a, t2.b, t3.a + t3.b; + QUERY PLAN +--------------------------------------------------------------------------------------------------------------- + Sort + Output: prt1_p1.a, prt1_p1.c, prt2_p1.b, prt2_p1.c, ((prt1_e_p1.a + prt1_e_p1.b)), prt1_e_p1.c + Sort Key: prt1_p1.a, prt2_p1.b, ((prt1_e_p1.a + prt1_e_p1.b)) + -> Result + Output: prt1_p1.a, prt1_p1.c, prt2_p1.b, prt2_p1.c, (prt1_e_p1.a + prt1_e_p1.b), prt1_e_p1.c + -> Append + -> Hash Full Join + Output: prt1_p1.a, prt1_p1.c, prt2_p1.b, prt2_p1.c, prt1_e_p1.a, prt1_e_p1.b, prt1_e_p1.c + Hash Cond: (prt1_p1.a = ((prt1_e_p1.a + prt1_e_p1.b) / 2)) + -> Hash Full Join + Output: prt1_p1.a, prt1_p1.c, prt2_p1.b, prt2_p1.c + Hash Cond: (prt1_p1.a = prt2_p1.b) + -> Seq Scan on public.prt1_p1 + Output: prt1_p1.a, prt1_p1.c + Filter: ((prt1_p1.a % 25) = 0) + -> Hash + Output: prt2_p1.b, prt2_p1.c + -> Seq Scan on public.prt2_p1 + Output: prt2_p1.b, prt2_p1.c + Filter: ((prt2_p1.b % 25) = 0) + -> Hash + Output: prt1_e_p1.a, prt1_e_p1.b, prt1_e_p1.c + -> Seq Scan on public.prt1_e_p1 + Output: prt1_e_p1.a, prt1_e_p1.b, prt1_e_p1.c + Filter: ((prt1_e_p1.a % 25) = 0) + -> Hash Full Join + Output: prt1_p2.a, prt1_p2.c, prt2_p2.b, prt2_p2.c, prt1_e_p2.a, prt1_e_p2.b, prt1_e_p2.c + Hash Cond: (prt1_p2.a = ((prt1_e_p2.a + prt1_e_p2.b) / 2)) + -> Hash Full Join + Output: prt1_p2.a, prt1_p2.c, prt2_p2.b, prt2_p2.c + Hash Cond: (prt1_p2.a = prt2_p2.b) + -> Seq Scan on public.prt1_p2 + Output: prt1_p2.a, prt1_p2.c + Filter: ((prt1_p2.a % 25) = 0) + -> Hash + Output: prt2_p2.b, prt2_p2.c + -> Seq Scan on public.prt2_p2 + Output: prt2_p2.b, prt2_p2.c + Filter: ((prt2_p2.b % 25) = 0) + -> Hash + Output: prt1_e_p2.a, prt1_e_p2.b, prt1_e_p2.c + -> Seq Scan on public.prt1_e_p2 + Output: prt1_e_p2.a, prt1_e_p2.b, prt1_e_p2.c + Filter: ((prt1_e_p2.a % 25) = 0) + -> Hash Full Join + Output: prt1_p3.a, prt1_p3.c, prt2_p3.b, prt2_p3.c, prt1_e_p3.a, prt1_e_p3.b, prt1_e_p3.c + Hash Cond: (prt1_p3.a = ((prt1_e_p3.a + prt1_e_p3.b) / 2)) + -> Hash Full Join + Output: prt1_p3.a, prt1_p3.c, prt2_p3.b, prt2_p3.c + Hash Cond: (prt1_p3.a = prt2_p3.b) + -> Seq Scan on public.prt1_p3 + Output: prt1_p3.a, prt1_p3.c + Filter: ((prt1_p3.a % 25) = 0) + -> Hash + Output: prt2_p3.b, prt2_p3.c + -> Seq Scan on public.prt2_p3 + Output: prt2_p3.b, prt2_p3.c + Filter: ((prt2_p3.b % 25) = 0) + -> Hash + Output: prt1_e_p3.a, prt1_e_p3.b, prt1_e_p3.c + -> Seq Scan on public.prt1_e_p3 + Output: prt1_e_p3.a, prt1_e_p3.b, prt1_e_p3.c + Filter: ((prt1_e_p3.a % 25) = 0) +(63 rows) + +SELECT t1.a, t1.c, t2.b, t2.c, t3.a + t3.b, t3.c FROM ((SELECT * FROM prt1 WHERE prt1.a % 25 = 0) t1 FULL JOIN (SELECT * FROM prt2 WHERE prt2.b % 25 = 0) t2 ON (t1.a = t2.b)) FULL JOIN (SELECT * FROM prt1_e WHERE prt1_e.a % 25 = 0) t3 ON (t1.a = (t3.a + t3.b)/2) ORDER BY t1.a, t2.b, t3.a + t3.b; + a | c | b | c | ?column? | c +-----+------+-----+------+----------+------ + 0 | 0000 | 0 | 0000 | 0 | 0000 + 50 | 0050 | | | 100 | 0050 + 100 | 0100 | | | 200 | 0100 + 150 | 0150 | 150 | 0150 | 300 | 0150 + 200 | 0200 | | | 400 | 0200 + 250 | 0250 | | | 500 | 0250 + 300 | 0300 | 300 | 0300 | 600 | 0300 + 350 | 0350 | | | 700 | 0350 + 400 | 0400 | | | 800 | 0400 + 450 | 0450 | 450 | 0450 | 900 | 0450 + 500 | 0500 | | | 1000 | 0500 + 550 | 0550 | | | 1100 | 0550 + | | 75 | 0075 | | + | | 225 | 0225 | | + | | 375 | 0375 | | + | | 525 | 0525 | | +(16 rows) + +SELECT t1.a, t1.c, t2.b, t2.c, t3.a + t3.b, t3.c FROM ((SELECT * FROM uprt1 WHERE uprt1.a % 25 = 0) t1 FULL JOIN (SELECT * FROM uprt2 WHERE uprt2.b % 25 = 0) t2 ON (t1.a = t2.b)) FULL JOIN (SELECT * FROM uprt1_e WHERE uprt1_e.a % 25 = 0) t3 ON (t1.a = (t3.a + t3.b)/2) ORDER BY t1.a, t2.b, t3.a + t3.b; + a | c | b | c | ?column? | c +-----+------+-----+------+----------+------ + 0 | 0000 | 0 | 0000 | 0 | 0000 + 50 | 0050 | | | 100 | 0050 + 100 | 0100 | | | 200 | 0100 + 150 | 0150 | 150 | 0150 | 300 | 0150 + 200 | 0200 | | | 400 | 0200 + 250 | 0250 | | | 500 | 0250 + 300 | 0300 | 300 | 0300 | 600 | 0300 + 350 | 0350 | | | 700 | 0350 + 400 | 0400 | | | 800 | 0400 + 450 | 0450 | 450 | 0450 | 900 | 0450 + 500 | 0500 | | | 1000 | 0500 + 550 | 0550 | | | 1100 | 0550 + | | 75 | 0075 | | + | | 225 | 0225 | | + | | 375 | 0375 | | + | | 525 | 0525 | | +(16 rows) + +-- Cases with non-nullable expressions in subquery results; +-- make sure these go to null as expected +EXPLAIN (VERBOSE, COSTS OFF) +SELECT t1.a, t1.phv, t2.b, t2.phv, t3.a + t3.b, t3.phv FROM ((SELECT 50 phv, * FROM prt1 WHERE prt1.a % 25 = 0) t1 FULL JOIN (SELECT 75 phv, * FROM prt2 WHERE prt2.b % 25 = 0) t2 ON (t1.a = t2.b)) FULL JOIN (SELECT 50 phv, * FROM prt1_e WHERE prt1_e.a % 25 = 0) t3 ON (t1.a = (t3.a + t3.b)/2) WHERE t1.a = t1.phv OR t2.b = t2.phv OR (t3.a + t3.b)/2 = t3.phv ORDER BY t1.a, t2.b, t3.a + t3.b; + QUERY PLAN +---------------------------------------------------------------------------------------------------------------------- + Sort + Output: prt1_p1.a, (50), prt2_p1.b, (75), ((prt1_e_p1.a + prt1_e_p1.b)), (50) + Sort Key: prt1_p1.a, prt2_p1.b, ((prt1_e_p1.a + prt1_e_p1.b)) + -> Result + Output: prt1_p1.a, (50), prt2_p1.b, (75), (prt1_e_p1.a + prt1_e_p1.b), (50) + -> Append + -> Hash Full Join + Output: prt1_p1.a, prt2_p1.b, prt1_e_p1.a, prt1_e_p1.b, (50), (75), (50) + Hash Cond: (prt1_p1.a = ((prt1_e_p1.a + prt1_e_p1.b) / 2)) + Filter: ((prt1_p1.a = (50)) OR (prt2_p1.b = (75)) OR (((prt1_e_p1.a + prt1_e_p1.b) / 2) = (50))) + -> Hash Full Join + Output: prt1_p1.a, prt2_p1.b, (50), (75) + Hash Cond: (prt1_p1.a = prt2_p1.b) + -> Seq Scan on public.prt1_p1 + Output: prt1_p1.a, 50 + Filter: ((prt1_p1.a % 25) = 0) + -> Hash + Output: prt2_p1.b, (75) + -> Seq Scan on public.prt2_p1 + Output: prt2_p1.b, 75 + Filter: ((prt2_p1.b % 25) = 0) + -> Hash + Output: prt1_e_p1.a, prt1_e_p1.b, (50) + -> Seq Scan on public.prt1_e_p1 + Output: prt1_e_p1.a, prt1_e_p1.b, 50 + Filter: ((prt1_e_p1.a % 25) = 0) + -> Hash Full Join + Output: prt1_p2.a, prt2_p2.b, prt1_e_p2.a, prt1_e_p2.b, (50), (75), (50) + Hash Cond: (prt1_p2.a = ((prt1_e_p2.a + prt1_e_p2.b) / 2)) + Filter: ((prt1_p2.a = (50)) OR (prt2_p2.b = (75)) OR (((prt1_e_p2.a + prt1_e_p2.b) / 2) = (50))) + -> Hash Full Join + Output: prt1_p2.a, prt2_p2.b, (50), (75) + Hash Cond: (prt1_p2.a = prt2_p2.b) + -> Seq Scan on public.prt1_p2 + Output: prt1_p2.a, 50 + Filter: ((prt1_p2.a % 25) = 0) + -> Hash + Output: prt2_p2.b, (75) + -> Seq Scan on public.prt2_p2 + Output: prt2_p2.b, 75 + Filter: ((prt2_p2.b % 25) = 0) + -> Hash + Output: prt1_e_p2.a, prt1_e_p2.b, (50) + -> Seq Scan on public.prt1_e_p2 + Output: prt1_e_p2.a, prt1_e_p2.b, 50 + Filter: ((prt1_e_p2.a % 25) = 0) + -> Hash Full Join + Output: prt1_p3.a, prt2_p3.b, prt1_e_p3.a, prt1_e_p3.b, (50), (75), (50) + Hash Cond: (prt1_p3.a = ((prt1_e_p3.a + prt1_e_p3.b) / 2)) + Filter: ((prt1_p3.a = (50)) OR (prt2_p3.b = (75)) OR (((prt1_e_p3.a + prt1_e_p3.b) / 2) = (50))) + -> Hash Full Join + Output: prt1_p3.a, prt2_p3.b, (50), (75) + Hash Cond: (prt1_p3.a = prt2_p3.b) + -> Seq Scan on public.prt1_p3 + Output: prt1_p3.a, 50 + Filter: ((prt1_p3.a % 25) = 0) + -> Hash + Output: prt2_p3.b, (75) + -> Seq Scan on public.prt2_p3 + Output: prt2_p3.b, 75 + Filter: ((prt2_p3.b % 25) = 0) + -> Hash + Output: prt1_e_p3.a, prt1_e_p3.b, (50) + -> Seq Scan on public.prt1_e_p3 + Output: prt1_e_p3.a, prt1_e_p3.b, 50 + Filter: ((prt1_e_p3.a % 25) = 0) +(66 rows) + +SELECT t1.a, t1.phv, t2.b, t2.phv, t3.a + t3.b, t3.phv FROM ((SELECT 50 phv, * FROM prt1 WHERE prt1.a % 25 = 0) t1 FULL JOIN (SELECT 75 phv, * FROM prt2 WHERE prt2.b % 25 = 0) t2 ON (t1.a = t2.b)) FULL JOIN (SELECT 50 phv, * FROM prt1_e WHERE prt1_e.a % 25 = 0) t3 ON (t1.a = (t3.a + t3.b)/2) WHERE t1.a = t1.phv OR t2.b = t2.phv OR (t3.a + t3.b)/2 = t3.phv ORDER BY t1.a, t2.b, t3.a + t3.b; + a | phv | b | phv | ?column? | phv +----+-----+----+-----+----------+----- + 50 | 50 | | | 100 | 50 + | | 75 | 75 | | +(2 rows) + +SELECT t1.a, t1.phv, t2.b, t2.phv, t3.a + t3.b, t3.phv FROM ((SELECT 50 phv, * FROM uprt1 WHERE uprt1.a % 25 = 0) t1 FULL JOIN (SELECT 75 phv, * FROM uprt2 WHERE uprt2.b % 25 = 0) t2 ON (t1.a = t2.b)) FULL JOIN (SELECT 50 phv, * FROM uprt1_e WHERE uprt1_e.a % 25 = 0) t3 ON (t1.a = (t3.a + t3.b)/2) WHERE t1.a = t1.phv OR t2.b = t2.phv OR (t3.a + t3.b)/2 = t3.phv ORDER BY t1.a, t2.b, t3.a + t3.b; + a | phv | b | phv | ?column? | phv +----+-----+----+-----+----------+----- + 50 | 50 | | | 100 | 50 + | | 75 | 75 | | +(2 rows) + +-- Semi-join +EXPLAIN (VERBOSE, COSTS OFF) +SELECT t1.* FROM prt1 t1 WHERE t1.a IN (SELECT t1.b FROM prt2 t1, prt1_e t2 WHERE t1.b % 25 = 0 AND t1.b = (t2.a + t2.b)/2) AND t1.a % 25 = 0 ORDER BY t1.a; + QUERY PLAN +------------------------------------------------------------------- + Merge Append + Sort Key: t1.a + -> Merge Semi Join + Output: t1.a, t1.b, t1.c + Merge Cond: (t1.a = t1_3.b) + -> Sort + Output: t1.a, t1.b, t1.c + Sort Key: t1.a + -> Seq Scan on public.prt1_p1 t1 + Output: t1.a, t1.b, t1.c + Filter: ((t1.a % 25) = 0) + -> Sort + Output: t1_3.b, t2.a, t2.b + Sort Key: t1_3.b + -> Hash Join + Output: t1_3.b, t2.a, t2.b + Hash Cond: (((t2.a + t2.b) / 2) = t1_3.b) + -> Seq Scan on public.prt1_e_p1 t2 + Output: t2.a, t2.b + -> Hash + Output: t1_3.b + -> Seq Scan on public.prt2_p1 t1_3 + Output: t1_3.b + Filter: ((t1_3.b % 25) = 0) + -> Merge Semi Join + Output: t1_2.a, t1_2.b, t1_2.c + Merge Cond: (t1_2.a = t1_4.b) + -> Sort + Output: t1_2.a, t1_2.b, t1_2.c + Sort Key: t1_2.a + -> Seq Scan on public.prt1_p2 t1_2 + Output: t1_2.a, t1_2.b, t1_2.c + Filter: ((t1_2.a % 25) = 0) + -> Sort + Output: t1_4.b, t2_1.a, t2_1.b + Sort Key: t1_4.b + -> Hash Join + Output: t1_4.b, t2_1.a, t2_1.b + Hash Cond: (((t2_1.a + t2_1.b) / 2) = t1_4.b) + -> Seq Scan on public.prt1_e_p2 t2_1 + Output: t2_1.a, t2_1.b + -> Hash + Output: t1_4.b + -> Seq Scan on public.prt2_p2 t1_4 + Output: t1_4.b + Filter: ((t1_4.b % 25) = 0) + -> Merge Semi Join + Output: t1_1.a, t1_1.b, t1_1.c + Merge Cond: (t1_1.a = t1_5.b) + -> Sort + Output: t1_1.a, t1_1.b, t1_1.c + Sort Key: t1_1.a + -> Seq Scan on public.prt1_p3 t1_1 + Output: t1_1.a, t1_1.b, t1_1.c + Filter: ((t1_1.a % 25) = 0) + -> Sort + Output: t1_5.b, t2_2.a, t2_2.b + Sort Key: t1_5.b + -> Hash Join + Output: t1_5.b, t2_2.a, t2_2.b + Hash Cond: (((t2_2.a + t2_2.b) / 2) = t1_5.b) + -> Seq Scan on public.prt1_e_p3 t2_2 + Output: t2_2.a, t2_2.b + -> Hash + Output: t1_5.b + -> Seq Scan on public.prt2_p3 t1_5 + Output: t1_5.b + Filter: ((t1_5.b % 25) = 0) +(68 rows) + +SELECT t1.* FROM prt1 t1 WHERE t1.a IN (SELECT t1.b FROM prt2 t1, prt1_e t2 WHERE t1.b % 25 = 0 AND t1.b = (t2.a + t2.b)/2) AND t1.a % 25 = 0 ORDER BY t1.a; + a | b | c +-----+-----+------ + 0 | 0 | 0000 + 150 | 150 | 0150 + 300 | 300 | 0300 + 450 | 450 | 0450 +(4 rows) + +SELECT t1.* FROM uprt1 t1 WHERE t1.a IN (SELECT t1.b FROM uprt2 t1, uprt1_e t2 WHERE t1.b % 25 = 0 AND t1.b = (t2.a + t2.b)/2) AND t1.a % 25 = 0 ORDER BY t1.a; + a | b | c +-----+-----+------ + 0 | 0 | 0000 + 150 | 150 | 0150 + 300 | 300 | 0300 + 450 | 450 | 0450 +(4 rows) + +EXPLAIN (VERBOSE, COSTS OFF) +SELECT t1.* FROM prt1 t1 WHERE t1.a IN (SELECT t1.b FROM prt2 t1 WHERE t1.b IN (SELECT (t1.a + t1.b)/2 FROM prt1_e t1 WHERE t1.a %25 = 0)) AND t1.a % 25 = 0 ORDER BY t1.a; + QUERY PLAN +------------------------------------------------------------------- + Merge Append + Sort Key: t1.a + -> Merge Semi Join + Output: t1.a, t1.b, t1.c + Merge Cond: (t1.a = t1_3.b) + -> Sort + Output: t1.a, t1.b, t1.c + Sort Key: t1.a + -> Seq Scan on public.prt1_p1 t1 + Output: t1.a, t1.b, t1.c + Filter: ((t1.a % 25) = 0) + -> Sort + Output: t1_3.b, t1_6.a, t1_6.b + Sort Key: t1_3.b + -> Hash Semi Join + Output: t1_3.b, t1_6.a, t1_6.b + Hash Cond: (t1_3.b = ((t1_6.a + t1_6.b) / 2)) + -> Seq Scan on public.prt2_p1 t1_3 + Output: t1_3.b + -> Hash + Output: t1_6.a, t1_6.b + -> Seq Scan on public.prt1_e_p1 t1_6 + Output: t1_6.a, t1_6.b + Filter: ((t1_6.a % 25) = 0) + -> Merge Semi Join + Output: t1_2.a, t1_2.b, t1_2.c + Merge Cond: (t1_2.a = t1_4.b) + -> Sort + Output: t1_2.a, t1_2.b, t1_2.c + Sort Key: t1_2.a + -> Seq Scan on public.prt1_p2 t1_2 + Output: t1_2.a, t1_2.b, t1_2.c + Filter: ((t1_2.a % 25) = 0) + -> Sort + Output: t1_4.b, t1_7.a, t1_7.b + Sort Key: t1_4.b + -> Hash Semi Join + Output: t1_4.b, t1_7.a, t1_7.b + Hash Cond: (t1_4.b = ((t1_7.a + t1_7.b) / 2)) + -> Seq Scan on public.prt2_p2 t1_4 + Output: t1_4.b + -> Hash + Output: t1_7.a, t1_7.b + -> Seq Scan on public.prt1_e_p2 t1_7 + Output: t1_7.a, t1_7.b + Filter: ((t1_7.a % 25) = 0) + -> Merge Semi Join + Output: t1_1.a, t1_1.b, t1_1.c + Merge Cond: (t1_1.a = t1_5.b) + -> Sort + Output: t1_1.a, t1_1.b, t1_1.c + Sort Key: t1_1.a + -> Seq Scan on public.prt1_p3 t1_1 + Output: t1_1.a, t1_1.b, t1_1.c + Filter: ((t1_1.a % 25) = 0) + -> Sort + Output: t1_5.b, t1_8.a, t1_8.b + Sort Key: t1_5.b + -> Hash Semi Join + Output: t1_5.b, t1_8.a, t1_8.b + Hash Cond: (t1_5.b = ((t1_8.a + t1_8.b) / 2)) + -> Seq Scan on public.prt2_p3 t1_5 + Output: t1_5.b + -> Hash + Output: t1_8.a, t1_8.b + -> Seq Scan on public.prt1_e_p3 t1_8 + Output: t1_8.a, t1_8.b + Filter: ((t1_8.a % 25) = 0) +(68 rows) + +SELECT t1.* FROM prt1 t1 WHERE t1.a IN (SELECT t1.b FROM prt2 t1 WHERE t1.b IN (SELECT (t1.a + t1.b)/2 FROM prt1_e t1 WHERE t1.a %25 = 0)) AND t1.a % 25 = 0 ORDER BY t1.a; + a | b | c +-----+-----+------ + 0 | 0 | 0000 + 150 | 150 | 0150 + 300 | 300 | 0300 + 450 | 450 | 0450 +(4 rows) + +SELECT t1.* FROM uprt1 t1 WHERE t1.a IN (SELECT t1.b FROM uprt2 t1 WHERE t1.b IN (SELECT (t1.a + t1.b)/2 FROM uprt1_e t1 WHERE t1.a %25 = 0)) AND t1.a % 25 = 0 ORDER BY t1.a; + a | b | c +-----+-----+------ + 0 | 0 | 0000 + 150 | 150 | 0150 + 300 | 300 | 0300 + 450 | 450 | 0450 +(4 rows) + +-- test merge joins with and without using indexes +SET enable_hashjoin TO off; +SET enable_nestloop TO off; +CREATE INDEX iprt1_p1_a on prt1_p1(a); +CREATE INDEX iprt1_p2_a on prt1_p2(a); +CREATE INDEX iprt1_p3_a on prt1_p3(a); +CREATE INDEX iprt2_p1_b on prt2_p1(b); +CREATE INDEX iprt2_p2_b on prt2_p2(b); +CREATE INDEX iprt2_p3_b on prt2_p3(b); +CREATE INDEX iprt1_e_p1_ab2 on prt1_e_p1(((a+b)/2)); +CREATE INDEX iprt1_e_p2_ab2 on prt1_e_p2(((a+b)/2)); +CREATE INDEX iprt1_e_p3_ab2 on prt1_e_p3(((a+b)/2)); +ANALYZE prt1; +ANALYZE prt1_p1; +ANALYZE prt1_p2; +ANALYZE prt1_p3; +ANALYZE prt2; +ANALYZE prt2_p1; +ANALYZE prt2_p2; +ANALYZE prt2_p3; +ANALYZE prt1_e; +ANALYZE prt1_e_p1; +ANALYZE prt1_e_p2; +ANALYZE prt1_e_p3; +EXPLAIN (VERBOSE, COSTS OFF) +SELECT t1.a, t1.c, t2.b, t2.c, t3.a + t3.b, t3.c FROM (prt1 t1 RIGHT JOIN prt2 t2 ON t1.a = t2.b) RIGHT JOIN prt1_e t3 ON (t2.b = (t3.a + t3.b)/2) WHERE t3.a % 25 = 0 ORDER BY t1.a, t2.b, t3.a + t3.b; + QUERY PLAN +----------------------------------------------------------------------------------------------------- + Sort + Output: t1.a, t1.c, t2.b, t2.c, ((t3.a + t3.b)), t3.c + Sort Key: t1.a, t2.b, ((t3.a + t3.b)) + -> Result + Output: t1.a, t1.c, t2.b, t2.c, (t3.a + t3.b), t3.c + -> Append + -> Merge Left Join + Output: t3.a, t3.b, t3.c, t2.b, t2.c, t1.a, t1.c + Merge Cond: (t2.b = t1.a) + -> Sort + Output: t3.a, t3.b, t3.c, t2.b, t2.c + Sort Key: t2.b + -> Merge Left Join + Output: t3.a, t3.b, t3.c, t2.b, t2.c + Merge Cond: ((((t3.a + t3.b) / 2)) = t2.b) + -> Sort + Output: t3.a, t3.b, t3.c, (((t3.a + t3.b) / 2)) + Sort Key: (((t3.a + t3.b) / 2)) + -> Seq Scan on public.prt1_e_p1 t3 + Output: t3.a, t3.b, t3.c, ((t3.a + t3.b) / 2) + Filter: ((t3.a % 25) = 0) + -> Sort + Output: t2.b, t2.c + Sort Key: t2.b + -> Seq Scan on public.prt2_p1 t2 + Output: t2.b, t2.c + -> Sort + Output: t1.a, t1.c + Sort Key: t1.a + -> Seq Scan on public.prt1_p1 t1 + Output: t1.a, t1.c + -> Merge Left Join + Output: t3_1.a, t3_1.b, t3_1.c, t2_1.b, t2_1.c, t1_2.a, t1_2.c + Merge Cond: (t2_1.b = t1_2.a) + -> Sort + Output: t3_1.a, t3_1.b, t3_1.c, t2_1.b, t2_1.c + Sort Key: t2_1.b + -> Merge Left Join + Output: t3_1.a, t3_1.b, t3_1.c, t2_1.b, t2_1.c + Merge Cond: ((((t3_1.a + t3_1.b) / 2)) = t2_1.b) + -> Sort + Output: t3_1.a, t3_1.b, t3_1.c, (((t3_1.a + t3_1.b) / 2)) + Sort Key: (((t3_1.a + t3_1.b) / 2)) + -> Seq Scan on public.prt1_e_p2 t3_1 + Output: t3_1.a, t3_1.b, t3_1.c, ((t3_1.a + t3_1.b) / 2) + Filter: ((t3_1.a % 25) = 0) + -> Sort + Output: t2_1.b, t2_1.c + Sort Key: t2_1.b + -> Seq Scan on public.prt2_p2 t2_1 + Output: t2_1.b, t2_1.c + -> Sort + Output: t1_2.a, t1_2.c + Sort Key: t1_2.a + -> Seq Scan on public.prt1_p2 t1_2 + Output: t1_2.a, t1_2.c + -> Merge Left Join + Output: t3_2.a, t3_2.b, t3_2.c, t2_2.b, t2_2.c, t1_1.a, t1_1.c + Merge Cond: (t2_2.b = t1_1.a) + -> Sort + Output: t3_2.a, t3_2.b, t3_2.c, t2_2.b, t2_2.c + Sort Key: t2_2.b + -> Merge Left Join + Output: t3_2.a, t3_2.b, t3_2.c, t2_2.b, t2_2.c + Merge Cond: ((((t3_2.a + t3_2.b) / 2)) = t2_2.b) + -> Sort + Output: t3_2.a, t3_2.b, t3_2.c, (((t3_2.a + t3_2.b) / 2)) + Sort Key: (((t3_2.a + t3_2.b) / 2)) + -> Seq Scan on public.prt1_e_p3 t3_2 + Output: t3_2.a, t3_2.b, t3_2.c, ((t3_2.a + t3_2.b) / 2) + Filter: ((t3_2.a % 25) = 0) + -> Sort + Output: t2_2.b, t2_2.c + Sort Key: t2_2.b + -> Seq Scan on public.prt2_p3 t2_2 + Output: t2_2.b, t2_2.c + -> Sort + Output: t1_1.a, t1_1.c + Sort Key: t1_1.a + -> Seq Scan on public.prt1_p3 t1_1 + Output: t1_1.a, t1_1.c +(81 rows) + +SELECT t1.a, t1.c, t2.b, t2.c, t3.a + t3.b, t3.c FROM (prt1 t1 RIGHT JOIN prt2 t2 ON t1.a = t2.b) RIGHT JOIN prt1_e t3 ON (t2.b = (t3.a + t3.b)/2) WHERE t3.a % 25 = 0 ORDER BY t1.a, t2.b, t3.a + t3.b; + a | c | b | c | ?column? | c +-----+------+-----+------+----------+------ + 0 | 0000 | 0 | 0000 | 0 | 0000 + 150 | 0150 | 150 | 0150 | 300 | 0150 + 300 | 0300 | 300 | 0300 | 600 | 0300 + 450 | 0450 | 450 | 0450 | 900 | 0450 + | | | | 100 | 0050 + | | | | 200 | 0100 + | | | | 400 | 0200 + | | | | 500 | 0250 + | | | | 700 | 0350 + | | | | 800 | 0400 + | | | | 1000 | 0500 + | | | | 1100 | 0550 +(12 rows) + +SELECT t1.a, t1.c, t2.b, t2.c, t3.a + t3.b, t3.c FROM (uprt1 t1 RIGHT JOIN uprt2 t2 ON t1.a = t2.b) RIGHT JOIN uprt1_e t3 ON (t2.b = (t3.a + t3.b)/2) WHERE t3.a % 25 = 0 ORDER BY t1.a, t2.b, t3.a + t3.b; + a | c | b | c | ?column? | c +-----+------+-----+------+----------+------ + 0 | 0000 | 0 | 0000 | 0 | 0000 + 150 | 0150 | 150 | 0150 | 300 | 0150 + 300 | 0300 | 300 | 0300 | 600 | 0300 + 450 | 0450 | 450 | 0450 | 900 | 0450 + | | | | 100 | 0050 + | | | | 200 | 0100 + | | | | 400 | 0200 + | | | | 500 | 0250 + | | | | 700 | 0350 + | | | | 800 | 0400 + | | | | 1000 | 0500 + | | | | 1100 | 0550 +(12 rows) + +EXPLAIN (VERBOSE, COSTS OFF) +SELECT t1.* FROM prt1 t1 WHERE t1.a IN (SELECT t1.b FROM prt2 t1 WHERE t1.b IN (SELECT (t1.a + t1.b)/2 FROM prt1_e t1 WHERE t1.a %25 = 0)) AND t1.a % 25 = 0 ORDER BY t1.a; + QUERY PLAN +--------------------------------------------------------------------------------- + Merge Append + Sort Key: t1.a + -> Merge Semi Join + Output: t1.a, t1.b, t1.c + Merge Cond: (t1.a = t1_3.b) + -> Sort + Output: t1.a, t1.b, t1.c + Sort Key: t1.a + -> Seq Scan on public.prt1_p1 t1 + Output: t1.a, t1.b, t1.c + Filter: ((t1.a % 25) = 0) + -> Materialize + Output: t1_3.b, t1_6.a, t1_6.b + -> Merge Semi Join + Output: t1_3.b, t1_6.a, t1_6.b + Merge Cond: (t1_3.b = (((t1_6.a + t1_6.b) / 2))) + -> Sort + Output: t1_3.b + Sort Key: t1_3.b + -> Seq Scan on public.prt2_p1 t1_3 + Output: t1_3.b + -> Sort + Output: t1_6.a, t1_6.b, (((t1_6.a + t1_6.b) / 2)) + Sort Key: (((t1_6.a + t1_6.b) / 2)) + -> Seq Scan on public.prt1_e_p1 t1_6 + Output: t1_6.a, t1_6.b, ((t1_6.a + t1_6.b) / 2) + Filter: ((t1_6.a % 25) = 0) + -> Merge Semi Join + Output: t1_2.a, t1_2.b, t1_2.c + Merge Cond: (t1_2.a = t1_4.b) + -> Sort + Output: t1_2.a, t1_2.b, t1_2.c + Sort Key: t1_2.a + -> Seq Scan on public.prt1_p2 t1_2 + Output: t1_2.a, t1_2.b, t1_2.c + Filter: ((t1_2.a % 25) = 0) + -> Materialize + Output: t1_4.b, t1_7.a, t1_7.b + -> Merge Semi Join + Output: t1_4.b, t1_7.a, t1_7.b + Merge Cond: (t1_4.b = (((t1_7.a + t1_7.b) / 2))) + -> Sort + Output: t1_4.b + Sort Key: t1_4.b + -> Seq Scan on public.prt2_p2 t1_4 + Output: t1_4.b + -> Sort + Output: t1_7.a, t1_7.b, (((t1_7.a + t1_7.b) / 2)) + Sort Key: (((t1_7.a + t1_7.b) / 2)) + -> Seq Scan on public.prt1_e_p2 t1_7 + Output: t1_7.a, t1_7.b, ((t1_7.a + t1_7.b) / 2) + Filter: ((t1_7.a % 25) = 0) + -> Merge Semi Join + Output: t1_1.a, t1_1.b, t1_1.c + Merge Cond: (t1_1.a = t1_5.b) + -> Sort + Output: t1_1.a, t1_1.b, t1_1.c + Sort Key: t1_1.a + -> Seq Scan on public.prt1_p3 t1_1 + Output: t1_1.a, t1_1.b, t1_1.c + Filter: ((t1_1.a % 25) = 0) + -> Materialize + Output: t1_5.b, t1_8.a, t1_8.b + -> Merge Semi Join + Output: t1_5.b, t1_8.a, t1_8.b + Merge Cond: (t1_5.b = (((t1_8.a + t1_8.b) / 2))) + -> Sort + Output: t1_5.b + Sort Key: t1_5.b + -> Seq Scan on public.prt2_p3 t1_5 + Output: t1_5.b + -> Sort + Output: t1_8.a, t1_8.b, (((t1_8.a + t1_8.b) / 2)) + Sort Key: (((t1_8.a + t1_8.b) / 2)) + -> Seq Scan on public.prt1_e_p3 t1_8 + Output: t1_8.a, t1_8.b, ((t1_8.a + t1_8.b) / 2) + Filter: ((t1_8.a % 25) = 0) +(77 rows) + +SELECT t1.* FROM prt1 t1 WHERE t1.a IN (SELECT t1.b FROM prt2 t1 WHERE t1.b IN (SELECT (t1.a + t1.b)/2 FROM prt1_e t1 WHERE t1.a %25 = 0)) AND t1.a % 25 = 0 ORDER BY t1.a; + a | b | c +-----+-----+------ + 0 | 0 | 0000 + 150 | 150 | 0150 + 300 | 300 | 0300 + 450 | 450 | 0450 +(4 rows) + +SELECT t1.* FROM uprt1 t1 WHERE t1.a IN (SELECT t1.b FROM uprt2 t1 WHERE t1.b IN (SELECT (t1.a + t1.b)/2 FROM uprt1_e t1 WHERE t1.a %25 = 0)) AND t1.a % 25 = 0 ORDER BY t1.a; + a | b | c +-----+-----+------ + 0 | 0 | 0000 + 150 | 150 | 0150 + 300 | 300 | 0300 + 450 | 450 | 0450 +(4 rows) + +EXPLAIN (VERBOSE, COSTS OFF) +SELECT t1.a, t1.c, t2.b, t2.c, t3.a + t3.b, t3.c FROM (prt1 t1 LEFT JOIN prt2 t2 ON t1.a = t2.b) RIGHT JOIN prt1_e t3 ON (t1.a = (t3.a + t3.b)/2) WHERE t3.a % 25 = 0 ORDER BY t1.a, t2.b, t3.a + t3.b; + QUERY PLAN +----------------------------------------------------------------------------------------------------- + Sort + Output: t1.a, t1.c, t2.b, t2.c, ((t3.a + t3.b)), t3.c + Sort Key: t1.a, t2.b, ((t3.a + t3.b)) + -> Result + Output: t1.a, t1.c, t2.b, t2.c, (t3.a + t3.b), t3.c + -> Append + -> Merge Left Join + Output: t3.a, t3.b, t3.c, t1.a, t1.c, t2.b, t2.c + Merge Cond: (t1.a = t2.b) + -> Sort + Output: t3.a, t3.b, t3.c, t1.a, t1.c + Sort Key: t1.a + -> Merge Left Join + Output: t3.a, t3.b, t3.c, t1.a, t1.c + Merge Cond: ((((t3.a + t3.b) / 2)) = t1.a) + -> Sort + Output: t3.a, t3.b, t3.c, (((t3.a + t3.b) / 2)) + Sort Key: (((t3.a + t3.b) / 2)) + -> Seq Scan on public.prt1_e_p1 t3 + Output: t3.a, t3.b, t3.c, ((t3.a + t3.b) / 2) + Filter: ((t3.a % 25) = 0) + -> Sort + Output: t1.a, t1.c + Sort Key: t1.a + -> Seq Scan on public.prt1_p1 t1 + Output: t1.a, t1.c + -> Sort + Output: t2.b, t2.c + Sort Key: t2.b + -> Seq Scan on public.prt2_p1 t2 + Output: t2.b, t2.c + -> Merge Left Join + Output: t3_1.a, t3_1.b, t3_1.c, t1_2.a, t1_2.c, t2_1.b, t2_1.c + Merge Cond: (t1_2.a = t2_1.b) + -> Sort + Output: t3_1.a, t3_1.b, t3_1.c, t1_2.a, t1_2.c + Sort Key: t1_2.a + -> Merge Left Join + Output: t3_1.a, t3_1.b, t3_1.c, t1_2.a, t1_2.c + Merge Cond: ((((t3_1.a + t3_1.b) / 2)) = t1_2.a) + -> Sort + Output: t3_1.a, t3_1.b, t3_1.c, (((t3_1.a + t3_1.b) / 2)) + Sort Key: (((t3_1.a + t3_1.b) / 2)) + -> Seq Scan on public.prt1_e_p2 t3_1 + Output: t3_1.a, t3_1.b, t3_1.c, ((t3_1.a + t3_1.b) / 2) + Filter: ((t3_1.a % 25) = 0) + -> Sort + Output: t1_2.a, t1_2.c + Sort Key: t1_2.a + -> Seq Scan on public.prt1_p2 t1_2 + Output: t1_2.a, t1_2.c + -> Sort + Output: t2_1.b, t2_1.c + Sort Key: t2_1.b + -> Seq Scan on public.prt2_p2 t2_1 + Output: t2_1.b, t2_1.c + -> Merge Left Join + Output: t3_2.a, t3_2.b, t3_2.c, t1_1.a, t1_1.c, t2_2.b, t2_2.c + Merge Cond: (t1_1.a = t2_2.b) + -> Sort + Output: t3_2.a, t3_2.b, t3_2.c, t1_1.a, t1_1.c + Sort Key: t1_1.a + -> Merge Left Join + Output: t3_2.a, t3_2.b, t3_2.c, t1_1.a, t1_1.c + Merge Cond: ((((t3_2.a + t3_2.b) / 2)) = t1_1.a) + -> Sort + Output: t3_2.a, t3_2.b, t3_2.c, (((t3_2.a + t3_2.b) / 2)) + Sort Key: (((t3_2.a + t3_2.b) / 2)) + -> Seq Scan on public.prt1_e_p3 t3_2 + Output: t3_2.a, t3_2.b, t3_2.c, ((t3_2.a + t3_2.b) / 2) + Filter: ((t3_2.a % 25) = 0) + -> Sort + Output: t1_1.a, t1_1.c + Sort Key: t1_1.a + -> Seq Scan on public.prt1_p3 t1_1 + Output: t1_1.a, t1_1.c + -> Sort + Output: t2_2.b, t2_2.c + Sort Key: t2_2.b + -> Seq Scan on public.prt2_p3 t2_2 + Output: t2_2.b, t2_2.c +(81 rows) + +SELECT t1.a, t1.c, t2.b, t2.c, t3.a + t3.b, t3.c FROM (prt1 t1 LEFT JOIN prt2 t2 ON t1.a = t2.b) RIGHT JOIN prt1_e t3 ON (t1.a = (t3.a + t3.b)/2) WHERE t3.a % 25 = 0 ORDER BY t1.a, t2.b, t3.a + t3.b; + a | c | b | c | ?column? | c +-----+------+-----+------+----------+------ + 0 | 0000 | 0 | 0000 | 0 | 0000 + 50 | 0050 | | | 100 | 0050 + 100 | 0100 | | | 200 | 0100 + 150 | 0150 | 150 | 0150 | 300 | 0150 + 200 | 0200 | | | 400 | 0200 + 250 | 0250 | | | 500 | 0250 + 300 | 0300 | 300 | 0300 | 600 | 0300 + 350 | 0350 | | | 700 | 0350 + 400 | 0400 | | | 800 | 0400 + 450 | 0450 | 450 | 0450 | 900 | 0450 + 500 | 0500 | | | 1000 | 0500 + 550 | 0550 | | | 1100 | 0550 +(12 rows) + +SELECT t1.a, t1.c, t2.b, t2.c, t3.a + t3.b, t3.c FROM (uprt1 t1 LEFT JOIN uprt2 t2 ON t1.a = t2.b) RIGHT JOIN uprt1_e t3 ON (t1.a = (t3.a + t3.b)/2) WHERE t3.a % 25 = 0 ORDER BY t1.a, t2.b, t3.a + t3.b; + a | c | b | c | ?column? | c +-----+------+-----+------+----------+------ + 0 | 0000 | 0 | 0000 | 0 | 0000 + 50 | 0050 | | | 100 | 0050 + 100 | 0100 | | | 200 | 0100 + 150 | 0150 | 150 | 0150 | 300 | 0150 + 200 | 0200 | | | 400 | 0200 + 250 | 0250 | | | 500 | 0250 + 300 | 0300 | 300 | 0300 | 600 | 0300 + 350 | 0350 | | | 700 | 0350 + 400 | 0400 | | | 800 | 0400 + 450 | 0450 | 450 | 0450 | 900 | 0450 + 500 | 0500 | | | 1000 | 0500 + 550 | 0550 | | | 1100 | 0550 +(12 rows) + +SET enable_seqscan TO off; +EXPLAIN (VERBOSE, COSTS OFF) +SELECT t1.a, t1.c, t2.b, t2.c, t3.a + t3.b, t3.c FROM (prt1 t1 RIGHT JOIN prt2 t2 ON t1.a = t2.b) RIGHT JOIN prt1_e t3 ON (t2.b = (t3.a + t3.b)/2) WHERE t3.a % 25 = 0 ORDER BY t1.a, t2.b, t3.a + t3.b; + QUERY PLAN +---------------------------------------------------------------------------------------------- + Sort + Output: t1.a, t1.c, t2.b, t2.c, ((t3.a + t3.b)), t3.c + Sort Key: t1.a, t2.b, ((t3.a + t3.b)) + -> Result + Output: t1.a, t1.c, t2.b, t2.c, (t3.a + t3.b), t3.c + -> Append + -> Merge Left Join + Output: t3.a, t3.b, t3.c, t2.b, t2.c, t1.a, t1.c + Merge Cond: (t2.b = t1.a) + -> Sort + Output: t3.a, t3.b, t3.c, t2.b, t2.c + Sort Key: t2.b + -> Merge Left Join + Output: t3.a, t3.b, t3.c, t2.b, t2.c + Merge Cond: (((t3.a + t3.b) / 2) = t2.b) + -> Index Scan using iprt1_e_p1_ab2 on public.prt1_e_p1 t3 + Output: t3.a, t3.b, t3.c + Filter: ((t3.a % 25) = 0) + -> Index Scan using iprt2_p1_b on public.prt2_p1 t2 + Output: t2.b, t2.c + -> Index Scan using iprt1_p1_a on public.prt1_p1 t1 + Output: t1.a, t1.c + -> Merge Left Join + Output: t3_1.a, t3_1.b, t3_1.c, t2_1.b, t2_1.c, t1_2.a, t1_2.c + Merge Cond: (t2_1.b = t1_2.a) + -> Sort + Output: t3_1.a, t3_1.b, t3_1.c, t2_1.b, t2_1.c + Sort Key: t2_1.b + -> Merge Left Join + Output: t3_1.a, t3_1.b, t3_1.c, t2_1.b, t2_1.c + Merge Cond: (((t3_1.a + t3_1.b) / 2) = t2_1.b) + -> Index Scan using iprt1_e_p2_ab2 on public.prt1_e_p2 t3_1 + Output: t3_1.a, t3_1.b, t3_1.c + Filter: ((t3_1.a % 25) = 0) + -> Index Scan using iprt2_p2_b on public.prt2_p2 t2_1 + Output: t2_1.b, t2_1.c + -> Index Scan using iprt1_p2_a on public.prt1_p2 t1_2 + Output: t1_2.a, t1_2.c + -> Merge Right Join + Output: t3_2.a, t3_2.b, t3_2.c, t2_2.b, t2_2.c, t1_1.a, t1_1.c + Merge Cond: (t2_2.b = ((t3_2.a + t3_2.b) / 2)) + -> Merge Left Join + Output: t2_2.b, t2_2.c, t1_1.a, t1_1.c + Merge Cond: (t2_2.b = t1_1.a) + -> Index Scan using iprt2_p3_b on public.prt2_p3 t2_2 + Output: t2_2.b, t2_2.c + -> Index Scan using iprt1_p3_a on public.prt1_p3 t1_1 + Output: t1_1.a, t1_1.c + -> Index Scan using iprt1_e_p3_ab2 on public.prt1_e_p3 t3_2 + Output: t3_2.a, t3_2.b, t3_2.c + Filter: ((t3_2.a % 25) = 0) +(51 rows) + +SELECT t1.a, t1.c, t2.b, t2.c, t3.a + t3.b, t3.c FROM (prt1 t1 RIGHT JOIN prt2 t2 ON t1.a = t2.b) RIGHT JOIN prt1_e t3 ON (t2.b = (t3.a + t3.b)/2) WHERE t3.a % 25 = 0 ORDER BY t1.a, t2.b, t3.a + t3.b; + a | c | b | c | ?column? | c +-----+------+-----+------+----------+------ + 0 | 0000 | 0 | 0000 | 0 | 0000 + 150 | 0150 | 150 | 0150 | 300 | 0150 + 300 | 0300 | 300 | 0300 | 600 | 0300 + 450 | 0450 | 450 | 0450 | 900 | 0450 + | | | | 100 | 0050 + | | | | 200 | 0100 + | | | | 400 | 0200 + | | | | 500 | 0250 + | | | | 700 | 0350 + | | | | 800 | 0400 + | | | | 1000 | 0500 + | | | | 1100 | 0550 +(12 rows) + +SELECT t1.a, t1.c, t2.b, t2.c, t3.a + t3.b, t3.c FROM (uprt1 t1 RIGHT JOIN uprt2 t2 ON t1.a = t2.b) RIGHT JOIN uprt1_e t3 ON (t2.b = (t3.a + t3.b)/2) WHERE t3.a % 25 = 0 ORDER BY t1.a, t2.b, t3.a + t3.b; + a | c | b | c | ?column? | c +-----+------+-----+------+----------+------ + 0 | 0000 | 0 | 0000 | 0 | 0000 + 150 | 0150 | 150 | 0150 | 300 | 0150 + 300 | 0300 | 300 | 0300 | 600 | 0300 + 450 | 0450 | 450 | 0450 | 900 | 0450 + | | | | 100 | 0050 + | | | | 200 | 0100 + | | | | 400 | 0200 + | | | | 500 | 0250 + | | | | 700 | 0350 + | | | | 800 | 0400 + | | | | 1000 | 0500 + | | | | 1100 | 0550 +(12 rows) + +EXPLAIN (VERBOSE, COSTS OFF) +SELECT t1.* FROM prt1 t1 WHERE t1.a IN (SELECT t1.b FROM prt2 t1 WHERE t1.b IN (SELECT (t1.a + t1.b)/2 FROM prt1_e t1 WHERE t1.a %25 = 0)) AND t1.a % 25 = 0 ORDER BY t1.a; + QUERY PLAN +---------------------------------------------------------------------------------- + Merge Append + Sort Key: t1.a + -> Merge Semi Join + Output: t1.a, t1.b, t1.c + Merge Cond: (t1.a = t1_3.b) + -> Index Scan using iprt1_p1_a on public.prt1_p1 t1 + Output: t1.a, t1.b, t1.c + Filter: ((t1.a % 25) = 0) + -> Materialize + Output: t1_3.b, t1_6.a, t1_6.b + -> Merge Semi Join + Output: t1_3.b, t1_6.a, t1_6.b + Merge Cond: (t1_3.b = ((t1_6.a + t1_6.b) / 2)) + -> Index Only Scan using iprt2_p1_b on public.prt2_p1 t1_3 + Output: t1_3.b + -> Index Scan using iprt1_e_p1_ab2 on public.prt1_e_p1 t1_6 + Output: t1_6.a, t1_6.b + Filter: ((t1_6.a % 25) = 0) + -> Merge Semi Join + Output: t1_2.a, t1_2.b, t1_2.c + Merge Cond: (t1_2.a = t1_4.b) + -> Index Scan using iprt1_p2_a on public.prt1_p2 t1_2 + Output: t1_2.a, t1_2.b, t1_2.c + Filter: ((t1_2.a % 25) = 0) + -> Materialize + Output: t1_4.b, t1_7.a, t1_7.b + -> Merge Semi Join + Output: t1_4.b, t1_7.a, t1_7.b + Merge Cond: (t1_4.b = ((t1_7.a + t1_7.b) / 2)) + -> Index Only Scan using iprt2_p2_b on public.prt2_p2 t1_4 + Output: t1_4.b + -> Index Scan using iprt1_e_p2_ab2 on public.prt1_e_p2 t1_7 + Output: t1_7.a, t1_7.b + Filter: ((t1_7.a % 25) = 0) + -> Merge Semi Join + Output: t1_1.a, t1_1.b, t1_1.c + Merge Cond: (t1_1.a = t1_5.b) + -> Index Scan using iprt1_p3_a on public.prt1_p3 t1_1 + Output: t1_1.a, t1_1.b, t1_1.c + Filter: ((t1_1.a % 25) = 0) + -> Materialize + Output: t1_5.b, t1_8.a, t1_8.b + -> Merge Semi Join + Output: t1_5.b, t1_8.a, t1_8.b + Merge Cond: (t1_5.b = ((t1_8.a + t1_8.b) / 2)) + -> Index Only Scan using iprt2_p3_b on public.prt2_p3 t1_5 + Output: t1_5.b + -> Index Scan using iprt1_e_p3_ab2 on public.prt1_e_p3 t1_8 + Output: t1_8.a, t1_8.b + Filter: ((t1_8.a % 25) = 0) +(50 rows) + +SELECT t1.* FROM prt1 t1 WHERE t1.a IN (SELECT t1.b FROM prt2 t1 WHERE t1.b IN (SELECT (t1.a + t1.b)/2 FROM prt1_e t1 WHERE t1.a %25 = 0)) AND t1.a % 25 = 0 ORDER BY t1.a; + a | b | c +-----+-----+------ + 0 | 0 | 0000 + 150 | 150 | 0150 + 300 | 300 | 0300 + 450 | 450 | 0450 +(4 rows) + +SELECT t1.* FROM uprt1 t1 WHERE t1.a IN (SELECT t1.b FROM uprt2 t1 WHERE t1.b IN (SELECT (t1.a + t1.b)/2 FROM uprt1_e t1 WHERE t1.a %25 = 0)) AND t1.a % 25 = 0 ORDER BY t1.a; + a | b | c +-----+-----+------ + 0 | 0 | 0000 + 150 | 150 | 0150 + 300 | 300 | 0300 + 450 | 450 | 0450 +(4 rows) + +EXPLAIN (VERBOSE, COSTS OFF) +SELECT t1.a, t1.c, t2.b, t2.c, t3.a + t3.b, t3.c FROM (prt1 t1 LEFT JOIN prt2 t2 ON t1.a = t2.b) RIGHT JOIN prt1_e t3 ON (t1.a = (t3.a + t3.b)/2) WHERE t3.a % 25 = 0 ORDER BY t1.a, t2.b, t3.a + t3.b; + QUERY PLAN +---------------------------------------------------------------------------------------------- + Sort + Output: t1.a, t1.c, t2.b, t2.c, ((t3.a + t3.b)), t3.c + Sort Key: t1.a, t2.b, ((t3.a + t3.b)) + -> Result + Output: t1.a, t1.c, t2.b, t2.c, (t3.a + t3.b), t3.c + -> Append + -> Merge Left Join + Output: t3.a, t3.b, t3.c, t1.a, t1.c, t2.b, t2.c + Merge Cond: (t1.a = t2.b) + -> Sort + Output: t3.a, t3.b, t3.c, t1.a, t1.c + Sort Key: t1.a + -> Merge Left Join + Output: t3.a, t3.b, t3.c, t1.a, t1.c + Merge Cond: (((t3.a + t3.b) / 2) = t1.a) + -> Index Scan using iprt1_e_p1_ab2 on public.prt1_e_p1 t3 + Output: t3.a, t3.b, t3.c + Filter: ((t3.a % 25) = 0) + -> Index Scan using iprt1_p1_a on public.prt1_p1 t1 + Output: t1.a, t1.c + -> Index Scan using iprt2_p1_b on public.prt2_p1 t2 + Output: t2.b, t2.c + -> Merge Left Join + Output: t3_1.a, t3_1.b, t3_1.c, t1_2.a, t1_2.c, t2_1.b, t2_1.c + Merge Cond: (t1_2.a = t2_1.b) + -> Sort + Output: t3_1.a, t3_1.b, t3_1.c, t1_2.a, t1_2.c + Sort Key: t1_2.a + -> Merge Left Join + Output: t3_1.a, t3_1.b, t3_1.c, t1_2.a, t1_2.c + Merge Cond: (((t3_1.a + t3_1.b) / 2) = t1_2.a) + -> Index Scan using iprt1_e_p2_ab2 on public.prt1_e_p2 t3_1 + Output: t3_1.a, t3_1.b, t3_1.c + Filter: ((t3_1.a % 25) = 0) + -> Index Scan using iprt1_p2_a on public.prt1_p2 t1_2 + Output: t1_2.a, t1_2.c + -> Index Scan using iprt2_p2_b on public.prt2_p2 t2_1 + Output: t2_1.b, t2_1.c + -> Merge Left Join + Output: t3_2.a, t3_2.b, t3_2.c, t1_1.a, t1_1.c, t2_2.b, t2_2.c + Merge Cond: (t1_1.a = t2_2.b) + -> Sort + Output: t3_2.a, t3_2.b, t3_2.c, t1_1.a, t1_1.c + Sort Key: t1_1.a + -> Merge Left Join + Output: t3_2.a, t3_2.b, t3_2.c, t1_1.a, t1_1.c + Merge Cond: (((t3_2.a + t3_2.b) / 2) = t1_1.a) + -> Index Scan using iprt1_e_p3_ab2 on public.prt1_e_p3 t3_2 + Output: t3_2.a, t3_2.b, t3_2.c + Filter: ((t3_2.a % 25) = 0) + -> Index Scan using iprt1_p3_a on public.prt1_p3 t1_1 + Output: t1_1.a, t1_1.c + -> Index Scan using iprt2_p3_b on public.prt2_p3 t2_2 + Output: t2_2.b, t2_2.c +(54 rows) + +SELECT t1.a, t1.c, t2.b, t2.c, t3.a + t3.b, t3.c FROM (prt1 t1 LEFT JOIN prt2 t2 ON t1.a = t2.b) RIGHT JOIN prt1_e t3 ON (t1.a = (t3.a + t3.b)/2) WHERE t3.a % 25 = 0 ORDER BY t1.a, t2.b, t3.a + t3.b; + a | c | b | c | ?column? | c +-----+------+-----+------+----------+------ + 0 | 0000 | 0 | 0000 | 0 | 0000 + 50 | 0050 | | | 100 | 0050 + 100 | 0100 | | | 200 | 0100 + 150 | 0150 | 150 | 0150 | 300 | 0150 + 200 | 0200 | | | 400 | 0200 + 250 | 0250 | | | 500 | 0250 + 300 | 0300 | 300 | 0300 | 600 | 0300 + 350 | 0350 | | | 700 | 0350 + 400 | 0400 | | | 800 | 0400 + 450 | 0450 | 450 | 0450 | 900 | 0450 + 500 | 0500 | | | 1000 | 0500 + 550 | 0550 | | | 1100 | 0550 +(12 rows) + +SELECT t1.a, t1.c, t2.b, t2.c, t3.a + t3.b, t3.c FROM (uprt1 t1 LEFT JOIN uprt2 t2 ON t1.a = t2.b) RIGHT JOIN uprt1_e t3 ON (t1.a = (t3.a + t3.b)/2) WHERE t3.a % 25 = 0 ORDER BY t1.a, t2.b, t3.a + t3.b; + a | c | b | c | ?column? | c +-----+------+-----+------+----------+------ + 0 | 0000 | 0 | 0000 | 0 | 0000 + 50 | 0050 | | | 100 | 0050 + 100 | 0100 | | | 200 | 0100 + 150 | 0150 | 150 | 0150 | 300 | 0150 + 200 | 0200 | | | 400 | 0200 + 250 | 0250 | | | 500 | 0250 + 300 | 0300 | 300 | 0300 | 600 | 0300 + 350 | 0350 | | | 700 | 0350 + 400 | 0400 | | | 800 | 0400 + 450 | 0450 | 450 | 0450 | 900 | 0450 + 500 | 0500 | | | 1000 | 0500 + 550 | 0550 | | | 1100 | 0550 +(12 rows) + +-- lateral references and parameterized paths +EXPLAIN (VERBOSE, COSTS OFF) +SELECT * FROM prt1 t1 LEFT JOIN LATERAL + (SELECT t2.a AS t2a, t3.a AS t3a, least(t1.a,t2.a,t3.a) FROM prt1 t2 JOIN prt2 t3 ON (t2.a = t3.b)) ss + ON t1.a = ss.t2a WHERE t1.a % 25 = 0 ORDER BY t1.a; + QUERY PLAN +----------------------------------------------------------------------------------------------- + Result + Output: t1.a, t1.b, t1.c, t2.a, t3.a, (LEAST(t1.a, t2.a, t3.a)), t1.a + -> Merge Append + Sort Key: t1.a + -> Nested Loop Left Join + Output: t1.a, t1.b, t1.c, t2.a, t3.a, (LEAST(t1.a, t2.a, t3.a)) + -> Index Scan using iprt1_p1_a on public.prt1_p1 t1 + Output: t1.a, t1.b, t1.c + Filter: ((t1.a % 25) = 0) + -> Merge Join + Output: t2.a, t3.a, LEAST(t1.a, t2.a, t3.a) + Merge Cond: (t2.a = t3.b) + -> Index Only Scan using iprt1_p1_a on public.prt1_p1 t2 + Output: t2.a + Index Cond: (t2.a = t1.a) + -> Index Scan using iprt2_p1_b on public.prt2_p1 t3 + Output: t3.a, t3.b + -> Nested Loop Left Join + Output: t1_2.a, t1_2.b, t1_2.c, t2_2.a, t3_1.a, (LEAST(t1_2.a, t2_2.a, t3_1.a)) + -> Index Scan using iprt1_p2_a on public.prt1_p2 t1_2 + Output: t1_2.a, t1_2.b, t1_2.c + Filter: ((t1_2.a % 25) = 0) + -> Merge Join + Output: t2_2.a, t3_1.a, LEAST(t1_2.a, t2_2.a, t3_1.a) + Merge Cond: (t2_2.a = t3_1.b) + -> Index Only Scan using iprt1_p2_a on public.prt1_p2 t2_2 + Output: t2_2.a + Index Cond: (t2_2.a = t1_2.a) + -> Index Scan using iprt2_p2_b on public.prt2_p2 t3_1 + Output: t3_1.a, t3_1.b + -> Nested Loop Left Join + Output: t1_1.a, t1_1.b, t1_1.c, t2_1.a, t3_2.a, (LEAST(t1_1.a, t2_1.a, t3_2.a)) + -> Index Scan using iprt1_p3_a on public.prt1_p3 t1_1 + Output: t1_1.a, t1_1.b, t1_1.c + Filter: ((t1_1.a % 25) = 0) + -> Merge Join + Output: t2_1.a, t3_2.a, LEAST(t1_1.a, t2_1.a, t3_2.a) + Merge Cond: (t2_1.a = t3_2.b) + -> Index Only Scan using iprt1_p3_a on public.prt1_p3 t2_1 + Output: t2_1.a + Index Cond: (t2_1.a = t1_1.a) + -> Index Scan using iprt2_p3_b on public.prt2_p3 t3_2 + Output: t3_2.a, t3_2.b +(43 rows) + +SELECT * FROM prt1 t1 LEFT JOIN LATERAL + (SELECT t2.a AS t2a, t3.a AS t3a, least(t1.a,t2.a,t3.a) FROM prt1 t2 JOIN prt2 t3 ON (t2.a = t3.b)) ss + ON t1.a = ss.t2a WHERE t1.a % 25 = 0 ORDER BY t1.a; + a | b | c | t2a | t3a | least +-----+-----+------+-----+-----+------- + 0 | 0 | 0000 | 0 | 0 | 0 + 50 | 50 | 0050 | | | + 100 | 100 | 0100 | | | + 150 | 150 | 0150 | 150 | 150 | 150 + 200 | 200 | 0200 | | | + 250 | 250 | 0250 | | | + 300 | 300 | 0300 | 300 | 300 | 300 + 350 | 350 | 0350 | | | + 400 | 400 | 0400 | | | + 450 | 450 | 0450 | 450 | 450 | 450 + 500 | 500 | 0500 | | | + 550 | 550 | 0550 | | | +(12 rows) + +SELECT * FROM uprt1 t1 LEFT JOIN LATERAL + (SELECT t2.a AS t2a, t3.a AS t3a, least(t1.a,t2.a,t3.a) FROM uprt1 t2 JOIN uprt2 t3 ON (t2.a = t3.b)) ss + ON t1.a = ss.t2a WHERE t1.a % 25 = 0 ORDER BY t1.a; + a | b | c | t2a | t3a | least +-----+-----+------+-----+-----+------- + 0 | 0 | 0000 | 0 | 0 | 0 + 50 | 50 | 0050 | | | + 100 | 100 | 0100 | | | + 150 | 150 | 0150 | 150 | 150 | 150 + 200 | 200 | 0200 | | | + 250 | 250 | 0250 | | | + 300 | 300 | 0300 | 300 | 300 | 300 + 350 | 350 | 0350 | | | + 400 | 400 | 0400 | | | + 450 | 450 | 0450 | 450 | 450 | 450 + 500 | 500 | 0500 | | | + 550 | 550 | 0550 | | | +(12 rows) + +EXPLAIN (VERBOSE, COSTS OFF) +SELECT * FROM prt1 t1 LEFT JOIN LATERAL + (SELECT t2.a AS t2a, t3.a AS t3a, least(t1.a,t2.a,t3.a) FROM prt1 t2 JOIN prt2 t3 ON (t2.a = t3.b)) ss + ON t1.b = ss.t2a WHERE t1.a % 25 = 0 ORDER BY t1.a; + QUERY PLAN +--------------------------------------------------------------------------- + Nested Loop Left Join + Output: t1.a, t1.b, t1.c, t2.a, t3.a, (LEAST(t1.a, t2.a, t3.a)), t1.a + -> Merge Append + Sort Key: t1.a + -> Sort + Output: t1.a, t1.b, t1.c + Sort Key: t1.a + -> Seq Scan on public.prt1 t1 + Output: t1.a, t1.b, t1.c + Filter: ((t1.a % 25) = 0) + -> Index Scan using iprt1_p1_a on public.prt1_p1 t1_1 + Output: t1_1.a, t1_1.b, t1_1.c + Filter: ((t1_1.a % 25) = 0) + -> Index Scan using iprt1_p3_a on public.prt1_p3 t1_2 + Output: t1_2.a, t1_2.b, t1_2.c + Filter: ((t1_2.a % 25) = 0) + -> Index Scan using iprt1_p2_a on public.prt1_p2 t1_3 + Output: t1_3.a, t1_3.b, t1_3.c + Filter: ((t1_3.a % 25) = 0) + -> Append + -> Merge Join + Output: t2.a, t3.a, LEAST(t1.a, t2.a, t3.a) + Merge Cond: (t2.a = t3.b) + -> Index Only Scan using iprt1_p1_a on public.prt1_p1 t2 + Output: t2.a + Index Cond: (t2.a = t1.b) + -> Index Scan using iprt2_p1_b on public.prt2_p1 t3 + Output: t3.a, t3.b + -> Merge Join + Output: t2_2.a, t3_1.a, LEAST(t1.a, t2_2.a, t3_1.a) + Merge Cond: (t2_2.a = t3_1.b) + -> Index Only Scan using iprt1_p2_a on public.prt1_p2 t2_2 + Output: t2_2.a + Index Cond: (t2_2.a = t1.b) + -> Index Scan using iprt2_p2_b on public.prt2_p2 t3_1 + Output: t3_1.a, t3_1.b + -> Merge Join + Output: t2_1.a, t3_2.a, LEAST(t1.a, t2_1.a, t3_2.a) + Merge Cond: (t2_1.a = t3_2.b) + -> Index Only Scan using iprt1_p3_a on public.prt1_p3 t2_1 + Output: t2_1.a + Index Cond: (t2_1.a = t1.b) + -> Index Scan using iprt2_p3_b on public.prt2_p3 t3_2 + Output: t3_2.a, t3_2.b +(44 rows) + +SELECT * FROM prt1 t1 LEFT JOIN LATERAL + (SELECT t2.a AS t2a, t3.a AS t3a, least(t1.a,t2.a,t3.a) FROM prt1 t2 JOIN prt2 t3 ON (t2.a = t3.b)) ss + ON t1.b = ss.t2a WHERE t1.a % 25 = 0 ORDER BY t1.a; + a | b | c | t2a | t3a | least +-----+-----+------+-----+-----+------- + 0 | 0 | 0000 | 0 | 0 | 0 + 50 | 50 | 0050 | | | + 100 | 100 | 0100 | | | + 150 | 150 | 0150 | 150 | 150 | 150 + 200 | 200 | 0200 | | | + 250 | 250 | 0250 | | | + 300 | 300 | 0300 | 300 | 300 | 300 + 350 | 350 | 0350 | | | + 400 | 400 | 0400 | | | + 450 | 450 | 0450 | 450 | 450 | 450 + 500 | 500 | 0500 | | | + 550 | 550 | 0550 | | | +(12 rows) + +SELECT * FROM uprt1 t1 LEFT JOIN LATERAL + (SELECT t2.a AS t2a, t3.a AS t3a, least(t1.a,t2.a,t3.a) FROM uprt1 t2 JOIN uprt2 t3 ON (t2.a = t3.b)) ss + ON t1.b = ss.t2a WHERE t1.a % 25 = 0 ORDER BY t1.a; + a | b | c | t2a | t3a | least +-----+-----+------+-----+-----+------- + 0 | 0 | 0000 | 0 | 0 | 0 + 50 | 50 | 0050 | | | + 100 | 100 | 0100 | | | + 150 | 150 | 0150 | 150 | 150 | 150 + 200 | 200 | 0200 | | | + 250 | 250 | 0250 | | | + 300 | 300 | 0300 | 300 | 300 | 300 + 350 | 350 | 0350 | | | + 400 | 400 | 0400 | | | + 450 | 450 | 0450 | 450 | 450 | 450 + 500 | 500 | 0500 | | | + 550 | 550 | 0550 | | | +(12 rows) + +RESET enable_hashjoin; +RESET enable_nestloop; +RESET enable_seqscan; +-- +-- partitioned by multiple columns +-- +CREATE TABLE prt1_m (a int, b int, c varchar) PARTITION BY RANGE(a, ((a + b)/2)); +CREATE TABLE prt1_m_p1 PARTITION OF prt1_m FOR VALUES FROM (0, 0) TO (250, 250); +CREATE TABLE prt1_m_p2 PARTITION OF prt1_m FOR VALUES FROM (250, 250) TO (500, 500); +CREATE TABLE prt1_m_p3 PARTITION OF prt1_m FOR VALUES FROM (500, 500) TO (600, 600); +INSERT INTO prt1_m SELECT i, i, to_char(i, 'FM0000') FROM generate_series(0, 599, 2) i; +ANALYZE prt1_m; +ANALYZE prt1_m_p1; +ANALYZE prt1_m_p2; +ANALYZE prt1_m_p3; +-- TODO: This table is created only for testing the results. Remove once +-- results are tested. +CREATE TABLE uprt1_m AS SELECT * FROM prt1_m; +CREATE TABLE prt2_m (a int, b int, c varchar) PARTITION BY RANGE(((b + a)/2), b); +CREATE TABLE prt2_m_p1 PARTITION OF prt2_m FOR VALUES FROM (0, 0) TO (250, 250); +CREATE TABLE prt2_m_p2 PARTITION OF prt2_m FOR VALUES FROM (250, 250) TO (500, 500); +CREATE TABLE prt2_m_p3 PARTITION OF prt2_m FOR VALUES FROM (500, 500) TO (600, 600); +INSERT INTO prt2_m SELECT i, i, to_char(i, 'FM0000') FROM generate_series(0, 599, 3) i; +ANALYZE prt2_m; +ANALYZE prt2_m_p1; +ANALYZE prt2_m_p2; +ANALYZE prt2_m_p3; +-- TODO: This table is created only for testing the results. Remove once +-- results are tested. +CREATE TABLE uprt2_m AS SELECT * FROM prt2_m; +EXPLAIN (VERBOSE, COSTS OFF) +SELECT t1.a, t1.c, t2.b, t2.c FROM prt1_m t1 RIGHT JOIN prt2_m t2 ON t1.a = (t2.b + t2.a)/2 AND t2.b = (t1.a + t1.b)/2 WHERE t2.b % 25 = 0 ORDER BY t1.a, t2.b; + QUERY PLAN +------------------------------------------------------------------------------------------------------------ + Sort + Output: t1.a, t1.c, t2.b, t2.c + Sort Key: t1.a, t2.b + -> Result + Output: t1.a, t1.c, t2.b, t2.c + -> Append + -> Hash Right Join + Output: t2.b, t2.c, t1.a, t1.c + Hash Cond: ((((t1.a + t1.b) / 2) = t2.b) AND (t1.a = ((t2.b + t2.a) / 2))) + -> Seq Scan on public.prt1_m_p1 t1 + Output: t1.a, t1.c, t1.b + -> Hash + Output: t2.b, t2.c, t2.a + -> Seq Scan on public.prt2_m_p1 t2 + Output: t2.b, t2.c, t2.a + Filter: ((t2.b % 25) = 0) + -> Hash Right Join + Output: t2_1.b, t2_1.c, t1_1.a, t1_1.c + Hash Cond: ((((t1_1.a + t1_1.b) / 2) = t2_1.b) AND (t1_1.a = ((t2_1.b + t2_1.a) / 2))) + -> Seq Scan on public.prt1_m_p2 t1_1 + Output: t1_1.a, t1_1.c, t1_1.b + -> Hash + Output: t2_1.b, t2_1.c, t2_1.a + -> Seq Scan on public.prt2_m_p2 t2_1 + Output: t2_1.b, t2_1.c, t2_1.a + Filter: ((t2_1.b % 25) = 0) + -> Hash Right Join + Output: t2_2.b, t2_2.c, t1_2.a, t1_2.c + Hash Cond: ((((t1_2.a + t1_2.b) / 2) = t2_2.b) AND (t1_2.a = ((t2_2.b + t2_2.a) / 2))) + -> Seq Scan on public.prt1_m_p3 t1_2 + Output: t1_2.a, t1_2.c, t1_2.b + -> Hash + Output: t2_2.b, t2_2.c, t2_2.a + -> Seq Scan on public.prt2_m_p3 t2_2 + Output: t2_2.b, t2_2.c, t2_2.a + Filter: ((t2_2.b % 25) = 0) +(36 rows) + +SELECT t1.a, t1.c, t2.b, t2.c FROM prt1_m t1 RIGHT JOIN prt2_m t2 ON t1.a = (t2.b + t2.a)/2 AND t2.b = (t1.a + t1.b)/2 WHERE t2.b % 25 = 0 ORDER BY t1.a, t2.b; + a | c | b | c +-----+------+-----+------ + 0 | 0000 | 0 | 0000 + 150 | 0150 | 150 | 0150 + 300 | 0300 | 300 | 0300 + 450 | 0450 | 450 | 0450 + | | 75 | 0075 + | | 225 | 0225 + | | 375 | 0375 + | | 525 | 0525 +(8 rows) + +SELECT t1.a, t1.c, t2.b, t2.c FROM uprt1_m t1 RIGHT JOIN uprt2_m t2 ON t1.a = (t2.b + t2.a)/2 AND t2.b = (t1.a + t1.b)/2 WHERE t2.b % 25 = 0 ORDER BY t1.a, t2.b; + a | c | b | c +-----+------+-----+------ + 0 | 0000 | 0 | 0000 + 150 | 0150 | 150 | 0150 + 300 | 0300 | 300 | 0300 + 450 | 0450 | 450 | 0450 + | | 75 | 0075 + | | 225 | 0225 + | | 375 | 0375 + | | 525 | 0525 +(8 rows) + +EXPLAIN (VERBOSE, COSTS OFF) +SELECT t1.a, t1.c, t2.b, t2.c FROM (SELECT * FROM prt1_m WHERE prt1_m.a % 25 = 0) t1 FULL JOIN (SELECT * FROM prt2_m WHERE prt2_m.b % 25 = 0) t2 ON (t1.a = (t2.b + t2.a)/2 AND t2.b = (t1.a + t1.b)/2) ORDER BY t1.a, t2.b; + QUERY PLAN +------------------------------------------------------------------------------------------------------------------------------------ + Sort + Output: prt1_m_p1.a, prt1_m_p1.c, prt2_m_p1.b, prt2_m_p1.c + Sort Key: prt1_m_p1.a, prt2_m_p1.b + -> Append + -> Hash Full Join + Output: prt1_m_p1.a, prt1_m_p1.c, prt2_m_p1.b, prt2_m_p1.c + Hash Cond: ((prt1_m_p1.a = ((prt2_m_p1.b + prt2_m_p1.a) / 2)) AND (((prt1_m_p1.a + prt1_m_p1.b) / 2) = prt2_m_p1.b)) + -> Seq Scan on public.prt1_m_p1 + Output: prt1_m_p1.a, prt1_m_p1.c, prt1_m_p1.b + Filter: ((prt1_m_p1.a % 25) = 0) + -> Hash + Output: prt2_m_p1.b, prt2_m_p1.c, prt2_m_p1.a + -> Seq Scan on public.prt2_m_p1 + Output: prt2_m_p1.b, prt2_m_p1.c, prt2_m_p1.a + Filter: ((prt2_m_p1.b % 25) = 0) + -> Hash Full Join + Output: prt1_m_p2.a, prt1_m_p2.c, prt2_m_p2.b, prt2_m_p2.c + Hash Cond: ((prt1_m_p2.a = ((prt2_m_p2.b + prt2_m_p2.a) / 2)) AND (((prt1_m_p2.a + prt1_m_p2.b) / 2) = prt2_m_p2.b)) + -> Seq Scan on public.prt1_m_p2 + Output: prt1_m_p2.a, prt1_m_p2.c, prt1_m_p2.b + Filter: ((prt1_m_p2.a % 25) = 0) + -> Hash + Output: prt2_m_p2.b, prt2_m_p2.c, prt2_m_p2.a + -> Seq Scan on public.prt2_m_p2 + Output: prt2_m_p2.b, prt2_m_p2.c, prt2_m_p2.a + Filter: ((prt2_m_p2.b % 25) = 0) + -> Hash Full Join + Output: prt1_m_p3.a, prt1_m_p3.c, prt2_m_p3.b, prt2_m_p3.c + Hash Cond: ((prt1_m_p3.a = ((prt2_m_p3.b + prt2_m_p3.a) / 2)) AND (((prt1_m_p3.a + prt1_m_p3.b) / 2) = prt2_m_p3.b)) + -> Seq Scan on public.prt1_m_p3 + Output: prt1_m_p3.a, prt1_m_p3.c, prt1_m_p3.b + Filter: ((prt1_m_p3.a % 25) = 0) + -> Hash + Output: prt2_m_p3.b, prt2_m_p3.c, prt2_m_p3.a + -> Seq Scan on public.prt2_m_p3 + Output: prt2_m_p3.b, prt2_m_p3.c, prt2_m_p3.a + Filter: ((prt2_m_p3.b % 25) = 0) +(37 rows) + +SELECT t1.a, t1.c, t2.b, t2.c FROM (SELECT * FROM prt1_m WHERE prt1_m.a % 25 = 0) t1 FULL JOIN (SELECT * FROM prt2_m WHERE prt2_m.b % 25 = 0) t2 ON (t1.a = (t2.b + t2.a)/2 AND t2.b = (t1.a + t1.b)/2) ORDER BY t1.a, t2.b; + a | c | b | c +-----+------+-----+------ + 0 | 0000 | 0 | 0000 + 50 | 0050 | | + 100 | 0100 | | + 150 | 0150 | 150 | 0150 + 200 | 0200 | | + 250 | 0250 | | + 300 | 0300 | 300 | 0300 + 350 | 0350 | | + 400 | 0400 | | + 450 | 0450 | 450 | 0450 + 500 | 0500 | | + 550 | 0550 | | + | | 75 | 0075 + | | 225 | 0225 + | | 375 | 0375 + | | 525 | 0525 +(16 rows) + +SELECT t1.a, t1.c, t2.b, t2.c FROM (SELECT * FROM uprt1_m t1 WHERE t1.a % 25 = 0) t1 FULL JOIN (SELECT * FROM uprt2_m t2 WHERE t2.b % 25 = 0) t2 ON (t1.a = (t2.b + t2.a)/2 AND t2.b = (t1.a + t1.b)/2) ORDER BY t1.a, t2.b; + a | c | b | c +-----+------+-----+------ + 0 | 0000 | 0 | 0000 + 50 | 0050 | | + 100 | 0100 | | + 150 | 0150 | 150 | 0150 + 200 | 0200 | | + 250 | 0250 | | + 300 | 0300 | 300 | 0300 + 350 | 0350 | | + 400 | 0400 | | + 450 | 0450 | 450 | 0450 + 500 | 0500 | | + 550 | 0550 | | + | | 75 | 0075 + | | 225 | 0225 + | | 375 | 0375 + | | 525 | 0525 +(16 rows) + +-- +-- tests for list partitioned tables. +-- +CREATE TABLE plt1 (a int, b int, c text) PARTITION BY LIST(c); +CREATE TABLE plt1_p1 PARTITION OF plt1 FOR VALUES IN ('0000', '0003', '0004', '0010'); +CREATE TABLE plt1_p2 PARTITION OF plt1 FOR VALUES IN ('0001', '0005', '0002', '0009'); +CREATE TABLE plt1_p3 PARTITION OF plt1 FOR VALUES IN ('0006', '0007', '0008', '0011'); +INSERT INTO plt1 SELECT i, i, to_char(i/50, 'FM0000') FROM generate_series(0, 599, 2) i; +ANALYZE plt1; +ANALYZE plt1_p1; +ANALYZE plt1_p2; +ANALYZE plt1_p3; +-- TODO: This table is created only for testing the results. Remove once +-- results are tested. +CREATE TABLE uplt1 AS SELECT * FROM plt1; +CREATE TABLE plt2 (a int, b int, c text) PARTITION BY LIST(c); +CREATE TABLE plt2_p1 PARTITION OF plt2 FOR VALUES IN ('0000', '0003', '0004', '0010'); +CREATE TABLE plt2_p2 PARTITION OF plt2 FOR VALUES IN ('0001', '0005', '0002', '0009'); +CREATE TABLE plt2_p3 PARTITION OF plt2 FOR VALUES IN ('0006', '0007', '0008', '0011'); +INSERT INTO plt2 SELECT i, i, to_char(i/50, 'FM0000') FROM generate_series(0, 599, 3) i; +ANALYZE plt2; +ANALYZE plt2_p1; +ANALYZE plt2_p2; +ANALYZE plt2_p3; +-- TODO: This table is created only for testing the results. Remove once +-- results are tested. +CREATE TABLE uplt2 AS SELECT * FROM plt2; +-- +-- list partitioned by expression +-- +CREATE TABLE plt1_e (a int, b int, c text) PARTITION BY LIST(ltrim(c, 'A')); +CREATE TABLE plt1_e_p1 PARTITION OF plt1_e FOR VALUES IN ('0000', '0003', '0004', '0010'); +CREATE TABLE plt1_e_p2 PARTITION OF plt1_e FOR VALUES IN ('0001', '0005', '0002', '0009'); +CREATE TABLE plt1_e_p3 PARTITION OF plt1_e FOR VALUES IN ('0006', '0007', '0008', '0011'); +INSERT INTO plt1_e SELECT i, i, 'A' || to_char(i/50, 'FM0000') FROM generate_series(0, 599, 2) i; +ANALYZE plt1_e; +ANALYZE plt1_e_p1; +ANALYZE plt1_e_p2; +ANALYZE plt1_e_p3; +-- TODO: This table is created only for testing the results. Remove once +-- results are tested. +CREATE TABLE uplt1_e AS SELECT * FROM plt1_e; +-- +-- N-way join +-- +EXPLAIN (VERBOSE, COSTS OFF) +SELECT avg(t1.a), avg(t2.b), avg(t3.a + t3.b), t1.c, t2.c, t3.c FROM plt1 t1, plt2 t2, plt1_e t3 WHERE t1.c = t2.c AND ltrim(t3.c, 'A') = t1.c GROUP BY t1.c, t2.c, t3.c ORDER BY t1.c, t2.c, t3.c; + QUERY PLAN +------------------------------------------------------------------------------------------ + Sort + Output: (avg(t1.a)), (avg(t2.b)), (avg((t3.a + t3.b))), t1.c, t2.c, t3.c + Sort Key: t1.c, t3.c + -> HashAggregate + Output: avg(t1.a), avg(t2.b), avg((t3.a + t3.b)), t1.c, t2.c, t3.c + Group Key: t1.c, t2.c, t3.c + -> Result + Output: t1.c, t2.c, t3.c, t1.a, t2.b, t3.a, t3.b + -> Append + -> Hash Join + Output: t1.a, t1.c, t2.b, t2.c, t3.a, t3.b, t3.c + Hash Cond: (t1.c = t2.c) + -> Seq Scan on public.plt1_p1 t1 + Output: t1.a, t1.c + -> Hash + Output: t2.b, t2.c, t3.a, t3.b, t3.c + -> Hash Join + Output: t2.b, t2.c, t3.a, t3.b, t3.c + Hash Cond: (t2.c = ltrim(t3.c, 'A'::text)) + -> Seq Scan on public.plt2_p1 t2 + Output: t2.b, t2.c + -> Hash + Output: t3.a, t3.b, t3.c + -> Seq Scan on public.plt1_e_p1 t3 + Output: t3.a, t3.b, t3.c + -> Hash Join + Output: t1_1.a, t1_1.c, t2_1.b, t2_1.c, t3_1.a, t3_1.b, t3_1.c + Hash Cond: (t1_1.c = t2_1.c) + -> Seq Scan on public.plt1_p2 t1_1 + Output: t1_1.a, t1_1.c + -> Hash + Output: t2_1.b, t2_1.c, t3_1.a, t3_1.b, t3_1.c + -> Hash Join + Output: t2_1.b, t2_1.c, t3_1.a, t3_1.b, t3_1.c + Hash Cond: (t2_1.c = ltrim(t3_1.c, 'A'::text)) + -> Seq Scan on public.plt2_p2 t2_1 + Output: t2_1.b, t2_1.c + -> Hash + Output: t3_1.a, t3_1.b, t3_1.c + -> Seq Scan on public.plt1_e_p2 t3_1 + Output: t3_1.a, t3_1.b, t3_1.c + -> Hash Join + Output: t1_2.a, t1_2.c, t2_2.b, t2_2.c, t3_2.a, t3_2.b, t3_2.c + Hash Cond: (t1_2.c = t2_2.c) + -> Seq Scan on public.plt1_p3 t1_2 + Output: t1_2.a, t1_2.c + -> Hash + Output: t2_2.b, t2_2.c, t3_2.a, t3_2.b, t3_2.c + -> Hash Join + Output: t2_2.b, t2_2.c, t3_2.a, t3_2.b, t3_2.c + Hash Cond: (t2_2.c = ltrim(t3_2.c, 'A'::text)) + -> Seq Scan on public.plt2_p3 t2_2 + Output: t2_2.b, t2_2.c + -> Hash + Output: t3_2.a, t3_2.b, t3_2.c + -> Seq Scan on public.plt1_e_p3 t3_2 + Output: t3_2.a, t3_2.b, t3_2.c +(57 rows) + +SELECT avg(t1.a), avg(t2.b), avg(t3.a + t3.b), t1.c, t2.c, t3.c FROM plt1 t1, plt2 t2, plt1_e t3 WHERE t1.c = t2.c AND ltrim(t3.c, 'A') = t1.c GROUP BY t1.c, t2.c, t3.c ORDER BY t1.c, t2.c, t3.c; + avg | avg | avg | c | c | c +----------------------+----------------------+-----------------------+------+------+------- + 24.0000000000000000 | 24.0000000000000000 | 48.0000000000000000 | 0000 | 0000 | A0000 + 74.0000000000000000 | 75.0000000000000000 | 148.0000000000000000 | 0001 | 0001 | A0001 + 124.0000000000000000 | 124.5000000000000000 | 248.0000000000000000 | 0002 | 0002 | A0002 + 174.0000000000000000 | 174.0000000000000000 | 348.0000000000000000 | 0003 | 0003 | A0003 + 224.0000000000000000 | 225.0000000000000000 | 448.0000000000000000 | 0004 | 0004 | A0004 + 274.0000000000000000 | 274.5000000000000000 | 548.0000000000000000 | 0005 | 0005 | A0005 + 324.0000000000000000 | 324.0000000000000000 | 648.0000000000000000 | 0006 | 0006 | A0006 + 374.0000000000000000 | 375.0000000000000000 | 748.0000000000000000 | 0007 | 0007 | A0007 + 424.0000000000000000 | 424.5000000000000000 | 848.0000000000000000 | 0008 | 0008 | A0008 + 474.0000000000000000 | 474.0000000000000000 | 948.0000000000000000 | 0009 | 0009 | A0009 + 524.0000000000000000 | 525.0000000000000000 | 1048.0000000000000000 | 0010 | 0010 | A0010 + 574.0000000000000000 | 574.5000000000000000 | 1148.0000000000000000 | 0011 | 0011 | A0011 +(12 rows) + +SELECT avg(t1.a), avg(t2.b), avg(t3.a + t3.b), t1.c, t2.c, t3.c FROM uplt1 t1, uplt2 t2, uplt1_e t3 WHERE t1.c = t2.c AND ltrim(t3.c, 'A') = t1.c GROUP BY t1.c, t2.c, t3.c ORDER BY t1.c, t2.c, t3.c; + avg | avg | avg | c | c | c +----------------------+----------------------+-----------------------+------+------+------- + 24.0000000000000000 | 24.0000000000000000 | 48.0000000000000000 | 0000 | 0000 | A0000 + 74.0000000000000000 | 75.0000000000000000 | 148.0000000000000000 | 0001 | 0001 | A0001 + 124.0000000000000000 | 124.5000000000000000 | 248.0000000000000000 | 0002 | 0002 | A0002 + 174.0000000000000000 | 174.0000000000000000 | 348.0000000000000000 | 0003 | 0003 | A0003 + 224.0000000000000000 | 225.0000000000000000 | 448.0000000000000000 | 0004 | 0004 | A0004 + 274.0000000000000000 | 274.5000000000000000 | 548.0000000000000000 | 0005 | 0005 | A0005 + 324.0000000000000000 | 324.0000000000000000 | 648.0000000000000000 | 0006 | 0006 | A0006 + 374.0000000000000000 | 375.0000000000000000 | 748.0000000000000000 | 0007 | 0007 | A0007 + 424.0000000000000000 | 424.5000000000000000 | 848.0000000000000000 | 0008 | 0008 | A0008 + 474.0000000000000000 | 474.0000000000000000 | 948.0000000000000000 | 0009 | 0009 | A0009 + 524.0000000000000000 | 525.0000000000000000 | 1048.0000000000000000 | 0010 | 0010 | A0010 + 574.0000000000000000 | 574.5000000000000000 | 1148.0000000000000000 | 0011 | 0011 | A0011 +(12 rows) + +EXPLAIN (VERBOSE, COSTS OFF) +SELECT t1.a, t1.c, t2.b, t2.c, t3.a + t3.b, t3.c FROM (plt1 t1 LEFT JOIN plt2 t2 ON t1.a = t2.b AND t1.c = t2.c) LEFT JOIN plt1_e t3 ON (t1.a = t3.a AND ltrim(t3.c, 'A') = t1.c) WHERE t1.a % 25 = 0 ORDER BY t1.a, t2.b, t3.a + t3.b; + QUERY PLAN +-------------------------------------------------------------------------------------------- + Sort + Output: t1.a, t1.c, t2.b, t2.c, ((t3.a + t3.b)), t3.c + Sort Key: t1.a, t2.b, ((t3.a + t3.b)) + -> Result + Output: t1.a, t1.c, t2.b, t2.c, (t3.a + t3.b), t3.c + -> Append + -> Hash Right Join + Output: t1.a, t1.c, t2.b, t2.c, t3.a, t3.b, t3.c + Hash Cond: ((t3.a = t1.a) AND (ltrim(t3.c, 'A'::text) = t1.c)) + -> Seq Scan on public.plt1_e_p1 t3 + Output: t3.a, t3.b, t3.c + -> Hash + Output: t1.a, t1.c, t2.b, t2.c + -> Hash Right Join + Output: t1.a, t1.c, t2.b, t2.c + Hash Cond: ((t2.b = t1.a) AND (t2.c = t1.c)) + -> Seq Scan on public.plt2_p1 t2 + Output: t2.b, t2.c + -> Hash + Output: t1.a, t1.c + -> Seq Scan on public.plt1_p1 t1 + Output: t1.a, t1.c + Filter: ((t1.a % 25) = 0) + -> Hash Right Join + Output: t1_1.a, t1_1.c, t2_1.b, t2_1.c, t3_1.a, t3_1.b, t3_1.c + Hash Cond: ((t3_1.a = t1_1.a) AND (ltrim(t3_1.c, 'A'::text) = t1_1.c)) + -> Seq Scan on public.plt1_e_p2 t3_1 + Output: t3_1.a, t3_1.b, t3_1.c + -> Hash + Output: t1_1.a, t1_1.c, t2_1.b, t2_1.c + -> Hash Right Join + Output: t1_1.a, t1_1.c, t2_1.b, t2_1.c + Hash Cond: ((t2_1.b = t1_1.a) AND (t2_1.c = t1_1.c)) + -> Seq Scan on public.plt2_p2 t2_1 + Output: t2_1.b, t2_1.c + -> Hash + Output: t1_1.a, t1_1.c + -> Seq Scan on public.plt1_p2 t1_1 + Output: t1_1.a, t1_1.c + Filter: ((t1_1.a % 25) = 0) + -> Hash Right Join + Output: t1_2.a, t1_2.c, t2_2.b, t2_2.c, t3_2.a, t3_2.b, t3_2.c + Hash Cond: ((t3_2.a = t1_2.a) AND (ltrim(t3_2.c, 'A'::text) = t1_2.c)) + -> Seq Scan on public.plt1_e_p3 t3_2 + Output: t3_2.a, t3_2.b, t3_2.c + -> Hash + Output: t1_2.a, t1_2.c, t2_2.b, t2_2.c + -> Hash Right Join + Output: t1_2.a, t1_2.c, t2_2.b, t2_2.c + Hash Cond: ((t2_2.b = t1_2.a) AND (t2_2.c = t1_2.c)) + -> Seq Scan on public.plt2_p3 t2_2 + Output: t2_2.b, t2_2.c + -> Hash + Output: t1_2.a, t1_2.c + -> Seq Scan on public.plt1_p3 t1_2 + Output: t1_2.a, t1_2.c + Filter: ((t1_2.a % 25) = 0) +(57 rows) + +SELECT t1.a, t1.c, t2.b, t2.c, t3.a + t3.b, t3.c FROM (plt1 t1 LEFT JOIN plt2 t2 ON t1.a = t2.b AND t1.c = t2.c) LEFT JOIN plt1_e t3 ON (t1.a = t3.a AND ltrim(t3.c, 'A') = t1.c) WHERE t1.a % 25 = 0 ORDER BY t1.a, t2.b, t3.a + t3.b; + a | c | b | c | ?column? | c +-----+------+-----+------+----------+------- + 0 | 0000 | 0 | 0000 | 0 | A0000 + 50 | 0001 | | | 100 | A0001 + 100 | 0002 | | | 200 | A0002 + 150 | 0003 | 150 | 0003 | 300 | A0003 + 200 | 0004 | | | 400 | A0004 + 250 | 0005 | | | 500 | A0005 + 300 | 0006 | 300 | 0006 | 600 | A0006 + 350 | 0007 | | | 700 | A0007 + 400 | 0008 | | | 800 | A0008 + 450 | 0009 | 450 | 0009 | 900 | A0009 + 500 | 0010 | | | 1000 | A0010 + 550 | 0011 | | | 1100 | A0011 +(12 rows) + +SELECT t1.a, t1.c, t2.b, t2.c, t3.a + t3.b, t3.c FROM (uplt1 t1 LEFT JOIN uplt2 t2 ON t1.a = t2.b AND t1.c = t2.c) LEFT JOIN uplt1_e t3 ON (t1.a = t3.a AND ltrim(t3.c, 'A') = t1.c) WHERE t1.a % 25 = 0 ORDER BY t1.a, t2.b, t3.a + t3.b; + a | c | b | c | ?column? | c +-----+------+-----+------+----------+------- + 0 | 0000 | 0 | 0000 | 0 | A0000 + 50 | 0001 | | | 100 | A0001 + 100 | 0002 | | | 200 | A0002 + 150 | 0003 | 150 | 0003 | 300 | A0003 + 200 | 0004 | | | 400 | A0004 + 250 | 0005 | | | 500 | A0005 + 300 | 0006 | 300 | 0006 | 600 | A0006 + 350 | 0007 | | | 700 | A0007 + 400 | 0008 | | | 800 | A0008 + 450 | 0009 | 450 | 0009 | 900 | A0009 + 500 | 0010 | | | 1000 | A0010 + 550 | 0011 | | | 1100 | A0011 +(12 rows) + +EXPLAIN (VERBOSE, COSTS OFF) +SELECT t1.a, t1.c, t2.b, t2.c, t3.a + t3.b, t3.c FROM (plt1 t1 LEFT JOIN plt2 t2 ON t1.a = t2.b AND t1.c = t2.c) LEFT JOIN plt1_e t3 ON (t2.b = t3.a AND t2.c = ltrim(t3.c, 'A')) WHERE t1.a % 25 = 0 ORDER BY t1.a, t2.b, t3.a + t3.b; + QUERY PLAN +-------------------------------------------------------------------------------------------- + Sort + Output: t1.a, t1.c, t2.b, t2.c, ((t3.a + t3.b)), t3.c + Sort Key: t1.a, t2.b, ((t3.a + t3.b)) + -> Result + Output: t1.a, t1.c, t2.b, t2.c, (t3.a + t3.b), t3.c + -> Append + -> Hash Right Join + Output: t1.a, t1.c, t2.b, t2.c, t3.a, t3.b, t3.c + Hash Cond: ((t3.a = t2.b) AND (ltrim(t3.c, 'A'::text) = t2.c)) + -> Seq Scan on public.plt1_e_p1 t3 + Output: t3.a, t3.b, t3.c + -> Hash + Output: t1.a, t1.c, t2.b, t2.c + -> Hash Right Join + Output: t1.a, t1.c, t2.b, t2.c + Hash Cond: ((t2.b = t1.a) AND (t2.c = t1.c)) + -> Seq Scan on public.plt2_p1 t2 + Output: t2.b, t2.c + -> Hash + Output: t1.a, t1.c + -> Seq Scan on public.plt1_p1 t1 + Output: t1.a, t1.c + Filter: ((t1.a % 25) = 0) + -> Hash Right Join + Output: t1_1.a, t1_1.c, t2_1.b, t2_1.c, t3_1.a, t3_1.b, t3_1.c + Hash Cond: ((t3_1.a = t2_1.b) AND (ltrim(t3_1.c, 'A'::text) = t2_1.c)) + -> Seq Scan on public.plt1_e_p2 t3_1 + Output: t3_1.a, t3_1.b, t3_1.c + -> Hash + Output: t1_1.a, t1_1.c, t2_1.b, t2_1.c + -> Hash Right Join + Output: t1_1.a, t1_1.c, t2_1.b, t2_1.c + Hash Cond: ((t2_1.b = t1_1.a) AND (t2_1.c = t1_1.c)) + -> Seq Scan on public.plt2_p2 t2_1 + Output: t2_1.b, t2_1.c + -> Hash + Output: t1_1.a, t1_1.c + -> Seq Scan on public.plt1_p2 t1_1 + Output: t1_1.a, t1_1.c + Filter: ((t1_1.a % 25) = 0) + -> Hash Right Join + Output: t1_2.a, t1_2.c, t2_2.b, t2_2.c, t3_2.a, t3_2.b, t3_2.c + Hash Cond: ((t3_2.a = t2_2.b) AND (ltrim(t3_2.c, 'A'::text) = t2_2.c)) + -> Seq Scan on public.plt1_e_p3 t3_2 + Output: t3_2.a, t3_2.b, t3_2.c + -> Hash + Output: t1_2.a, t1_2.c, t2_2.b, t2_2.c + -> Hash Right Join + Output: t1_2.a, t1_2.c, t2_2.b, t2_2.c + Hash Cond: ((t2_2.b = t1_2.a) AND (t2_2.c = t1_2.c)) + -> Seq Scan on public.plt2_p3 t2_2 + Output: t2_2.b, t2_2.c + -> Hash + Output: t1_2.a, t1_2.c + -> Seq Scan on public.plt1_p3 t1_2 + Output: t1_2.a, t1_2.c + Filter: ((t1_2.a % 25) = 0) +(57 rows) + +SELECT t1.a, t1.c, t2.b, t2.c, t3.a + t3.b, t3.c FROM (plt1 t1 LEFT JOIN plt2 t2 ON t1.a = t2.b AND t1.c = t2.c) LEFT JOIN plt1_e t3 ON (t2.b = t3.a AND t2.c = ltrim(t3.c, 'A')) WHERE t1.a % 25 = 0 ORDER BY t1.a, t2.b, t3.a + t3.b; + a | c | b | c | ?column? | c +-----+------+-----+------+----------+------- + 0 | 0000 | 0 | 0000 | 0 | A0000 + 50 | 0001 | | | | + 100 | 0002 | | | | + 150 | 0003 | 150 | 0003 | 300 | A0003 + 200 | 0004 | | | | + 250 | 0005 | | | | + 300 | 0006 | 300 | 0006 | 600 | A0006 + 350 | 0007 | | | | + 400 | 0008 | | | | + 450 | 0009 | 450 | 0009 | 900 | A0009 + 500 | 0010 | | | | + 550 | 0011 | | | | +(12 rows) + +SELECT t1.a, t1.c, t2.b, t2.c, t3.a + t3.b, t3.c FROM (uplt1 t1 LEFT JOIN uplt2 t2 ON t1.a = t2.b AND t1.c = t2.c) LEFT JOIN uplt1_e t3 ON (t2.b = t3.a AND t2.c = ltrim(t3.c, 'A')) WHERE t1.a % 25 = 0 ORDER BY t1.a, t2.b, t3.a + t3.b; + a | c | b | c | ?column? | c +-----+------+-----+------+----------+------- + 0 | 0000 | 0 | 0000 | 0 | A0000 + 50 | 0001 | | | | + 100 | 0002 | | | | + 150 | 0003 | 150 | 0003 | 300 | A0003 + 200 | 0004 | | | | + 250 | 0005 | | | | + 300 | 0006 | 300 | 0006 | 600 | A0006 + 350 | 0007 | | | | + 400 | 0008 | | | | + 450 | 0009 | 450 | 0009 | 900 | A0009 + 500 | 0010 | | | | + 550 | 0011 | | | | +(12 rows) + +EXPLAIN (VERBOSE, COSTS OFF) +SELECT t1.a, t1.c, t2.b, t2.c, t3.a + t3.b, t3.c FROM (plt1 t1 LEFT JOIN plt2 t2 ON t1.a = t2.b AND t1.c = t2.c) RIGHT JOIN plt1_e t3 ON (t1.a = t3.a AND ltrim(t3.c, 'A') = t1.c) WHERE t3.a % 25 = 0 ORDER BY t1.a, t2.b, t3.a + t3.b; + QUERY PLAN +-------------------------------------------------------------------------------------------------------- + Sort + Output: t1.a, t1.c, t2.b, t2.c, ((t3.a + t3.b)), t3.c + Sort Key: t1.a, t2.b, ((t3.a + t3.b)) + -> Result + Output: t1.a, t1.c, t2.b, t2.c, (t3.a + t3.b), t3.c + -> Append + -> Hash Right Join + Output: t3.a, t3.b, t3.c, t1.a, t1.c, t2.b, t2.c + Hash Cond: ((t2.b = t1.a) AND (t2.c = t1.c)) + -> Seq Scan on public.plt2_p1 t2 + Output: t2.b, t2.c + -> Hash + Output: t3.a, t3.b, t3.c, t1.a, t1.c + -> Hash Right Join + Output: t3.a, t3.b, t3.c, t1.a, t1.c + Hash Cond: ((t1.c = ltrim(t3.c, 'A'::text)) AND (t1.a = t3.a)) + -> Seq Scan on public.plt1_p1 t1 + Output: t1.a, t1.c + -> Hash + Output: t3.a, t3.b, t3.c + -> Seq Scan on public.plt1_e_p1 t3 + Output: t3.a, t3.b, t3.c + Filter: ((t3.a % 25) = 0) + -> Hash Right Join + Output: t3_1.a, t3_1.b, t3_1.c, t1_1.a, t1_1.c, t2_1.b, t2_1.c + Hash Cond: ((t2_1.b = t1_1.a) AND (t2_1.c = t1_1.c)) + -> Seq Scan on public.plt2_p2 t2_1 + Output: t2_1.b, t2_1.c + -> Hash + Output: t3_1.a, t3_1.b, t3_1.c, t1_1.a, t1_1.c + -> Hash Right Join + Output: t3_1.a, t3_1.b, t3_1.c, t1_1.a, t1_1.c + Hash Cond: ((t1_1.c = ltrim(t3_1.c, 'A'::text)) AND (t1_1.a = t3_1.a)) + -> Seq Scan on public.plt1_p2 t1_1 + Output: t1_1.a, t1_1.c + -> Hash + Output: t3_1.a, t3_1.b, t3_1.c + -> Seq Scan on public.plt1_e_p2 t3_1 + Output: t3_1.a, t3_1.b, t3_1.c + Filter: ((t3_1.a % 25) = 0) + -> Hash Right Join + Output: t3_2.a, t3_2.b, t3_2.c, t1_2.a, t1_2.c, t2_2.b, t2_2.c + Hash Cond: ((t2_2.b = t1_2.a) AND (t2_2.c = t1_2.c)) + -> Seq Scan on public.plt2_p3 t2_2 + Output: t2_2.b, t2_2.c + -> Hash + Output: t3_2.a, t3_2.b, t3_2.c, t1_2.a, t1_2.c + -> Hash Right Join + Output: t3_2.a, t3_2.b, t3_2.c, t1_2.a, t1_2.c + Hash Cond: ((t1_2.c = ltrim(t3_2.c, 'A'::text)) AND (t1_2.a = t3_2.a)) + -> Seq Scan on public.plt1_p3 t1_2 + Output: t1_2.a, t1_2.c + -> Hash + Output: t3_2.a, t3_2.b, t3_2.c + -> Seq Scan on public.plt1_e_p3 t3_2 + Output: t3_2.a, t3_2.b, t3_2.c + Filter: ((t3_2.a % 25) = 0) +(57 rows) + +SELECT t1.a, t1.c, t2.b, t2.c, t3.a + t3.b, t3.c FROM (plt1 t1 LEFT JOIN plt2 t2 ON t1.a = t2.b AND t1.c = t2.c) RIGHT JOIN plt1_e t3 ON (t1.a = t3.a AND ltrim(t3.c, 'A') = t1.c) WHERE t3.a % 25 = 0 ORDER BY t1.a, t2.b, t3.a + t3.b; + a | c | b | c | ?column? | c +-----+------+-----+------+----------+------- + 0 | 0000 | 0 | 0000 | 0 | A0000 + 50 | 0001 | | | 100 | A0001 + 100 | 0002 | | | 200 | A0002 + 150 | 0003 | 150 | 0003 | 300 | A0003 + 200 | 0004 | | | 400 | A0004 + 250 | 0005 | | | 500 | A0005 + 300 | 0006 | 300 | 0006 | 600 | A0006 + 350 | 0007 | | | 700 | A0007 + 400 | 0008 | | | 800 | A0008 + 450 | 0009 | 450 | 0009 | 900 | A0009 + 500 | 0010 | | | 1000 | A0010 + 550 | 0011 | | | 1100 | A0011 +(12 rows) + +SELECT t1.a, t1.c, t2.b, t2.c, t3.a + t3.b, t3.c FROM (uplt1 t1 LEFT JOIN uplt2 t2 ON t1.a = t2.b AND t1.c = t2.c) RIGHT JOIN uplt1_e t3 ON (t1.a = t3.a AND ltrim(t3.c, 'A') = t1.c) WHERE t3.a % 25 = 0 ORDER BY t1.a, t2.b, t3.a + t3.b; + a | c | b | c | ?column? | c +-----+------+-----+------+----------+------- + 0 | 0000 | 0 | 0000 | 0 | A0000 + 50 | 0001 | | | 100 | A0001 + 100 | 0002 | | | 200 | A0002 + 150 | 0003 | 150 | 0003 | 300 | A0003 + 200 | 0004 | | | 400 | A0004 + 250 | 0005 | | | 500 | A0005 + 300 | 0006 | 300 | 0006 | 600 | A0006 + 350 | 0007 | | | 700 | A0007 + 400 | 0008 | | | 800 | A0008 + 450 | 0009 | 450 | 0009 | 900 | A0009 + 500 | 0010 | | | 1000 | A0010 + 550 | 0011 | | | 1100 | A0011 +(12 rows) + +EXPLAIN (VERBOSE, COSTS OFF) +SELECT t1.a, t1.c, t2.b, t2.c, t3.a + t3.b, t3.c FROM (plt1 t1 RIGHT JOIN plt2 t2 ON t1.a = t2.b AND t1.c = t2.c) RIGHT JOIN plt1_e t3 ON (t2.b = t3.a AND t2.c = ltrim(t3.c, 'A')) WHERE t3.a % 25 = 0 ORDER BY t1.a, t2.b, t3.a + t3.b; + QUERY PLAN +-------------------------------------------------------------------------------------------------------- + Sort + Output: t1.a, t1.c, t2.b, t2.c, ((t3.a + t3.b)), t3.c + Sort Key: t1.a, t2.b, ((t3.a + t3.b)) + -> Result + Output: t1.a, t1.c, t2.b, t2.c, (t3.a + t3.b), t3.c + -> Append + -> Hash Right Join + Output: t3.a, t3.b, t3.c, t2.b, t2.c, t1.a, t1.c + Hash Cond: ((t1.a = t2.b) AND (t1.c = t2.c)) + -> Seq Scan on public.plt1_p1 t1 + Output: t1.a, t1.c + -> Hash + Output: t3.a, t3.b, t3.c, t2.b, t2.c + -> Hash Right Join + Output: t3.a, t3.b, t3.c, t2.b, t2.c + Hash Cond: ((t2.b = t3.a) AND (t2.c = ltrim(t3.c, 'A'::text))) + -> Seq Scan on public.plt2_p1 t2 + Output: t2.b, t2.c + -> Hash + Output: t3.a, t3.b, t3.c + -> Seq Scan on public.plt1_e_p1 t3 + Output: t3.a, t3.b, t3.c + Filter: ((t3.a % 25) = 0) + -> Hash Right Join + Output: t3_1.a, t3_1.b, t3_1.c, t2_1.b, t2_1.c, t1_1.a, t1_1.c + Hash Cond: ((t1_1.a = t2_1.b) AND (t1_1.c = t2_1.c)) + -> Seq Scan on public.plt1_p2 t1_1 + Output: t1_1.a, t1_1.c + -> Hash + Output: t3_1.a, t3_1.b, t3_1.c, t2_1.b, t2_1.c + -> Hash Right Join + Output: t3_1.a, t3_1.b, t3_1.c, t2_1.b, t2_1.c + Hash Cond: ((t2_1.b = t3_1.a) AND (t2_1.c = ltrim(t3_1.c, 'A'::text))) + -> Seq Scan on public.plt2_p2 t2_1 + Output: t2_1.b, t2_1.c + -> Hash + Output: t3_1.a, t3_1.b, t3_1.c + -> Seq Scan on public.plt1_e_p2 t3_1 + Output: t3_1.a, t3_1.b, t3_1.c + Filter: ((t3_1.a % 25) = 0) + -> Hash Right Join + Output: t3_2.a, t3_2.b, t3_2.c, t2_2.b, t2_2.c, t1_2.a, t1_2.c + Hash Cond: ((t1_2.a = t2_2.b) AND (t1_2.c = t2_2.c)) + -> Seq Scan on public.plt1_p3 t1_2 + Output: t1_2.a, t1_2.c + -> Hash + Output: t3_2.a, t3_2.b, t3_2.c, t2_2.b, t2_2.c + -> Hash Right Join + Output: t3_2.a, t3_2.b, t3_2.c, t2_2.b, t2_2.c + Hash Cond: ((t2_2.b = t3_2.a) AND (t2_2.c = ltrim(t3_2.c, 'A'::text))) + -> Seq Scan on public.plt2_p3 t2_2 + Output: t2_2.b, t2_2.c + -> Hash + Output: t3_2.a, t3_2.b, t3_2.c + -> Seq Scan on public.plt1_e_p3 t3_2 + Output: t3_2.a, t3_2.b, t3_2.c + Filter: ((t3_2.a % 25) = 0) +(57 rows) + +SELECT t1.a, t1.c, t2.b, t2.c, t3.a + t3.b, t3.c FROM (plt1 t1 RIGHT JOIN plt2 t2 ON t1.a = t2.b AND t1.c = t2.c) RIGHT JOIN plt1_e t3 ON (t2.b = t3.a AND t2.c = ltrim(t3.c, 'A')) WHERE t3.a % 25 = 0 ORDER BY t1.a, t2.b, t3.a + t3.b; + a | c | b | c | ?column? | c +-----+------+-----+------+----------+------- + 0 | 0000 | 0 | 0000 | 0 | A0000 + 150 | 0003 | 150 | 0003 | 300 | A0003 + 300 | 0006 | 300 | 0006 | 600 | A0006 + 450 | 0009 | 450 | 0009 | 900 | A0009 + | | | | 100 | A0001 + | | | | 200 | A0002 + | | | | 400 | A0004 + | | | | 500 | A0005 + | | | | 700 | A0007 + | | | | 800 | A0008 + | | | | 1000 | A0010 + | | | | 1100 | A0011 +(12 rows) + +SELECT t1.a, t1.c, t2.b, t2.c, t3.a + t3.b, t3.c FROM (uplt1 t1 RIGHT JOIN uplt2 t2 ON t1.a = t2.b AND t1.c = t2.c) RIGHT JOIN uplt1_e t3 ON (t2.b = t3.a AND t2.c = ltrim(t3.c, 'A')) WHERE t3.a % 25 = 0 ORDER BY t1.a, t2.b, t3.a + t3.b; + a | c | b | c | ?column? | c +-----+------+-----+------+----------+------- + 0 | 0000 | 0 | 0000 | 0 | A0000 + 150 | 0003 | 150 | 0003 | 300 | A0003 + 300 | 0006 | 300 | 0006 | 600 | A0006 + 450 | 0009 | 450 | 0009 | 900 | A0009 + | | | | 100 | A0001 + | | | | 200 | A0002 + | | | | 400 | A0004 + | | | | 500 | A0005 + | | | | 700 | A0007 + | | | | 800 | A0008 + | | | | 1000 | A0010 + | | | | 1100 | A0011 +(12 rows) + +EXPLAIN (VERBOSE, COSTS OFF) +SELECT t1.a, t1.c, t2.b, t2.c, t3.a + t3.b, t3.c FROM ((SELECT * FROM plt1 WHERE plt1.a % 25 = 0) t1 FULL JOIN (SELECT * FROM plt2 WHERE plt2.b % 25 = 0) t2 ON (t1.a = t2.b AND t1.c = t2.c)) FULL JOIN (SELECT * FROM plt1_e WHERE plt1_e.a % 25 = 0) t3 ON (t1.a = t3.a AND ltrim(t3.c, 'A') = t1.c) ORDER BY t1.a, t2.b, t3.a + t3.b; + QUERY PLAN +--------------------------------------------------------------------------------------------------------------- + Sort + Output: plt1_p1.a, plt1_p1.c, plt2_p1.b, plt2_p1.c, ((plt1_e_p1.a + plt1_e_p1.b)), plt1_e_p1.c + Sort Key: plt1_p1.a, plt2_p1.b, ((plt1_e_p1.a + plt1_e_p1.b)) + -> Result + Output: plt1_p1.a, plt1_p1.c, plt2_p1.b, plt2_p1.c, (plt1_e_p1.a + plt1_e_p1.b), plt1_e_p1.c + -> Append + -> Hash Full Join + Output: plt1_p1.a, plt1_p1.c, plt2_p1.b, plt2_p1.c, plt1_e_p1.a, plt1_e_p1.b, plt1_e_p1.c + Hash Cond: ((plt1_p1.a = plt1_e_p1.a) AND (plt1_p1.c = ltrim(plt1_e_p1.c, 'A'::text))) + -> Hash Full Join + Output: plt1_p1.a, plt1_p1.c, plt2_p1.b, plt2_p1.c + Hash Cond: ((plt1_p1.a = plt2_p1.b) AND (plt1_p1.c = plt2_p1.c)) + -> Seq Scan on public.plt1_p1 + Output: plt1_p1.a, plt1_p1.c + Filter: ((plt1_p1.a % 25) = 0) + -> Hash + Output: plt2_p1.b, plt2_p1.c + -> Seq Scan on public.plt2_p1 + Output: plt2_p1.b, plt2_p1.c + Filter: ((plt2_p1.b % 25) = 0) + -> Hash + Output: plt1_e_p1.a, plt1_e_p1.b, plt1_e_p1.c + -> Seq Scan on public.plt1_e_p1 + Output: plt1_e_p1.a, plt1_e_p1.b, plt1_e_p1.c + Filter: ((plt1_e_p1.a % 25) = 0) + -> Hash Full Join + Output: plt1_p2.a, plt1_p2.c, plt2_p2.b, plt2_p2.c, plt1_e_p2.a, plt1_e_p2.b, plt1_e_p2.c + Hash Cond: ((plt1_p2.a = plt1_e_p2.a) AND (plt1_p2.c = ltrim(plt1_e_p2.c, 'A'::text))) + -> Hash Full Join + Output: plt1_p2.a, plt1_p2.c, plt2_p2.b, plt2_p2.c + Hash Cond: ((plt1_p2.a = plt2_p2.b) AND (plt1_p2.c = plt2_p2.c)) + -> Seq Scan on public.plt1_p2 + Output: plt1_p2.a, plt1_p2.c + Filter: ((plt1_p2.a % 25) = 0) + -> Hash + Output: plt2_p2.b, plt2_p2.c + -> Seq Scan on public.plt2_p2 + Output: plt2_p2.b, plt2_p2.c + Filter: ((plt2_p2.b % 25) = 0) + -> Hash + Output: plt1_e_p2.a, plt1_e_p2.b, plt1_e_p2.c + -> Seq Scan on public.plt1_e_p2 + Output: plt1_e_p2.a, plt1_e_p2.b, plt1_e_p2.c + Filter: ((plt1_e_p2.a % 25) = 0) + -> Hash Full Join + Output: plt1_p3.a, plt1_p3.c, plt2_p3.b, plt2_p3.c, plt1_e_p3.a, plt1_e_p3.b, plt1_e_p3.c + Hash Cond: ((plt1_p3.a = plt1_e_p3.a) AND (plt1_p3.c = ltrim(plt1_e_p3.c, 'A'::text))) + -> Hash Full Join + Output: plt1_p3.a, plt1_p3.c, plt2_p3.b, plt2_p3.c + Hash Cond: ((plt1_p3.a = plt2_p3.b) AND (plt1_p3.c = plt2_p3.c)) + -> Seq Scan on public.plt1_p3 + Output: plt1_p3.a, plt1_p3.c + Filter: ((plt1_p3.a % 25) = 0) + -> Hash + Output: plt2_p3.b, plt2_p3.c + -> Seq Scan on public.plt2_p3 + Output: plt2_p3.b, plt2_p3.c + Filter: ((plt2_p3.b % 25) = 0) + -> Hash + Output: plt1_e_p3.a, plt1_e_p3.b, plt1_e_p3.c + -> Seq Scan on public.plt1_e_p3 + Output: plt1_e_p3.a, plt1_e_p3.b, plt1_e_p3.c + Filter: ((plt1_e_p3.a % 25) = 0) +(63 rows) + +SELECT t1.a, t1.c, t2.b, t2.c, t3.a + t3.b, t3.c FROM ((SELECT * FROM plt1 WHERE plt1.a % 25 = 0) t1 FULL JOIN (SELECT * FROM plt2 WHERE plt2.b % 25 = 0) t2 ON (t1.a = t2.b AND t1.c = t2.c)) FULL JOIN (SELECT * FROM plt1_e WHERE plt1_e.a % 25 = 0) t3 ON (t1.a = t3.a AND ltrim(t3.c, 'A') = t1.c) ORDER BY t1.a, t2.b, t3.a + t3.b; + a | c | b | c | ?column? | c +-----+------+-----+------+----------+------- + 0 | 0000 | 0 | 0000 | 0 | A0000 + 50 | 0001 | | | 100 | A0001 + 100 | 0002 | | | 200 | A0002 + 150 | 0003 | 150 | 0003 | 300 | A0003 + 200 | 0004 | | | 400 | A0004 + 250 | 0005 | | | 500 | A0005 + 300 | 0006 | 300 | 0006 | 600 | A0006 + 350 | 0007 | | | 700 | A0007 + 400 | 0008 | | | 800 | A0008 + 450 | 0009 | 450 | 0009 | 900 | A0009 + 500 | 0010 | | | 1000 | A0010 + 550 | 0011 | | | 1100 | A0011 + | | 75 | 0001 | | + | | 225 | 0004 | | + | | 375 | 0007 | | + | | 525 | 0010 | | +(16 rows) + +SELECT t1.a, t1.c, t2.b, t2.c, t3.a + t3.b, t3.c FROM ((SELECT * FROM uplt1 WHERE uplt1.a % 25 = 0) t1 FULL JOIN (SELECT * FROM uplt2 WHERE uplt2.b % 25 = 0) t2 ON (t1.a = t2.b AND t1.c = t2.c)) FULL JOIN (SELECT * FROM uplt1_e WHERE uplt1_e.a % 25 = 0) t3 ON (t1.a = t3.a AND ltrim(t3.c, 'A') = t1.c) ORDER BY t1.a, t2.b, t3.a + t3.b; + a | c | b | c | ?column? | c +-----+------+-----+------+----------+------- + 0 | 0000 | 0 | 0000 | 0 | A0000 + 50 | 0001 | | | 100 | A0001 + 100 | 0002 | | | 200 | A0002 + 150 | 0003 | 150 | 0003 | 300 | A0003 + 200 | 0004 | | | 400 | A0004 + 250 | 0005 | | | 500 | A0005 + 300 | 0006 | 300 | 0006 | 600 | A0006 + 350 | 0007 | | | 700 | A0007 + 400 | 0008 | | | 800 | A0008 + 450 | 0009 | 450 | 0009 | 900 | A0009 + 500 | 0010 | | | 1000 | A0010 + 550 | 0011 | | | 1100 | A0011 + | | 75 | 0001 | | + | | 225 | 0004 | | + | | 375 | 0007 | | + | | 525 | 0010 | | +(16 rows) + +-- Semi-join +EXPLAIN (VERBOSE, COSTS OFF) +SELECT t1.* FROM plt1 t1 WHERE t1.c IN (SELECT t1.c FROM plt2 t1, plt1_e t2 WHERE t1.c = ltrim(t2.c, 'A')) AND t1.a % 25 = 0 ORDER BY t1.a; + QUERY PLAN +-------------------------------------------------------------------- + Sort + Output: t1.a, t1.b, t1.c + Sort Key: t1.a + -> Append + -> Nested Loop Semi Join + Output: t1.a, t1.b, t1.c + Join Filter: (t1.c = t1_3.c) + -> Seq Scan on public.plt1_p1 t1 + Output: t1.a, t1.b, t1.c + Filter: ((t1.a % 25) = 0) + -> Hash Join + Output: t1_3.c, t2.c + Hash Cond: (t1_3.c = ltrim(t2.c, 'A'::text)) + -> Seq Scan on public.plt2_p1 t1_3 + Output: t1_3.c + -> Hash + Output: t2.c + -> Seq Scan on public.plt1_e_p1 t2 + Output: t2.c + -> Nested Loop Semi Join + Output: t1_1.a, t1_1.b, t1_1.c + Join Filter: (t1_1.c = t1_4.c) + -> Seq Scan on public.plt1_p2 t1_1 + Output: t1_1.a, t1_1.b, t1_1.c + Filter: ((t1_1.a % 25) = 0) + -> Hash Join + Output: t1_4.c, t2_1.c + Hash Cond: (t1_4.c = ltrim(t2_1.c, 'A'::text)) + -> Seq Scan on public.plt2_p2 t1_4 + Output: t1_4.c + -> Hash + Output: t2_1.c + -> Seq Scan on public.plt1_e_p2 t2_1 + Output: t2_1.c + -> Nested Loop Semi Join + Output: t1_2.a, t1_2.b, t1_2.c + Join Filter: (t1_2.c = t1_5.c) + -> Seq Scan on public.plt1_p3 t1_2 + Output: t1_2.a, t1_2.b, t1_2.c + Filter: ((t1_2.a % 25) = 0) + -> Hash Join + Output: t1_5.c, t2_2.c + Hash Cond: (t1_5.c = ltrim(t2_2.c, 'A'::text)) + -> Seq Scan on public.plt2_p3 t1_5 + Output: t1_5.c + -> Hash + Output: t2_2.c + -> Seq Scan on public.plt1_e_p3 t2_2 + Output: t2_2.c +(49 rows) + +SELECT t1.* FROM plt1 t1 WHERE t1.c IN (SELECT t1.c FROM plt2 t1, plt1_e t2 WHERE t1.c = ltrim(t2.c, 'A')) AND t1.a % 25 = 0 ORDER BY t1.a; + a | b | c +-----+-----+------ + 0 | 0 | 0000 + 50 | 50 | 0001 + 100 | 100 | 0002 + 150 | 150 | 0003 + 200 | 200 | 0004 + 250 | 250 | 0005 + 300 | 300 | 0006 + 350 | 350 | 0007 + 400 | 400 | 0008 + 450 | 450 | 0009 + 500 | 500 | 0010 + 550 | 550 | 0011 +(12 rows) + +SELECT t1.* FROM uplt1 t1 WHERE t1.c IN (SELECT t1.c FROM uplt2 t1, uplt1_e t2 WHERE t1.c = ltrim(t2.c, 'A')) AND t1.a % 25 = 0 ORDER BY t1.a; + a | b | c +-----+-----+------ + 0 | 0 | 0000 + 50 | 50 | 0001 + 100 | 100 | 0002 + 150 | 150 | 0003 + 200 | 200 | 0004 + 250 | 250 | 0005 + 300 | 300 | 0006 + 350 | 350 | 0007 + 400 | 400 | 0008 + 450 | 450 | 0009 + 500 | 500 | 0010 + 550 | 550 | 0011 +(12 rows) + +EXPLAIN (VERBOSE, COSTS OFF) +SELECT t1.* FROM plt1 t1 WHERE t1.c IN (SELECT t1.c FROM plt2 t1 WHERE t1.c IN (SELECT ltrim(t1.c, 'A') FROM plt1_e t1 WHERE t1.a % 25 = 0)) AND t1.a % 25 = 0 ORDER BY t1.a; + QUERY PLAN +-------------------------------------------------------------------------------- + Sort + Output: t1.a, t1.b, t1.c + Sort Key: t1.a + -> Append + -> Nested Loop Semi Join + Output: t1.a, t1.b, t1.c + Join Filter: (t1.c = t1_3.c) + -> Seq Scan on public.plt1_p1 t1 + Output: t1.a, t1.b, t1.c + Filter: ((t1.a % 25) = 0) + -> Hash Join + Output: t1_3.c, t1_6.c + Hash Cond: (t1_3.c = ltrim(t1_6.c, 'A'::text)) + -> Seq Scan on public.plt2_p1 t1_3 + Output: t1_3.c + -> Hash + Output: t1_6.c + -> HashAggregate + Output: t1_6.c + Group Key: ltrim(t1_6.c, 'A'::text) + -> Seq Scan on public.plt1_e_p1 t1_6 + Output: t1_6.c, ltrim(t1_6.c, 'A'::text) + Filter: ((t1_6.a % 25) = 0) + -> Nested Loop Semi Join + Output: t1_1.a, t1_1.b, t1_1.c + Join Filter: (t1_1.c = t1_4.c) + -> Seq Scan on public.plt1_p2 t1_1 + Output: t1_1.a, t1_1.b, t1_1.c + Filter: ((t1_1.a % 25) = 0) + -> Hash Join + Output: t1_4.c, t1_7.c + Hash Cond: (t1_4.c = ltrim(t1_7.c, 'A'::text)) + -> Seq Scan on public.plt2_p2 t1_4 + Output: t1_4.c + -> Hash + Output: t1_7.c + -> HashAggregate + Output: t1_7.c + Group Key: ltrim(t1_7.c, 'A'::text) + -> Seq Scan on public.plt1_e_p2 t1_7 + Output: t1_7.c, ltrim(t1_7.c, 'A'::text) + Filter: ((t1_7.a % 25) = 0) + -> Nested Loop Semi Join + Output: t1_2.a, t1_2.b, t1_2.c + Join Filter: (t1_2.c = t1_5.c) + -> Seq Scan on public.plt1_p3 t1_2 + Output: t1_2.a, t1_2.b, t1_2.c + Filter: ((t1_2.a % 25) = 0) + -> Hash Join + Output: t1_5.c, t1_8.c + Hash Cond: (t1_5.c = ltrim(t1_8.c, 'A'::text)) + -> Seq Scan on public.plt2_p3 t1_5 + Output: t1_5.c + -> Hash + Output: t1_8.c + -> HashAggregate + Output: t1_8.c + Group Key: ltrim(t1_8.c, 'A'::text) + -> Seq Scan on public.plt1_e_p3 t1_8 + Output: t1_8.c, ltrim(t1_8.c, 'A'::text) + Filter: ((t1_8.a % 25) = 0) +(61 rows) + +SELECT t1.* FROM plt1 t1 WHERE t1.c IN (SELECT t1.c FROM plt2 t1 WHERE t1.c IN (SELECT ltrim(t1.c, 'A') FROM plt1_e t1 WHERE t1.a % 25 = 0)) AND t1.a % 25 = 0 ORDER BY t1.a; + a | b | c +-----+-----+------ + 0 | 0 | 0000 + 50 | 50 | 0001 + 100 | 100 | 0002 + 150 | 150 | 0003 + 200 | 200 | 0004 + 250 | 250 | 0005 + 300 | 300 | 0006 + 350 | 350 | 0007 + 400 | 400 | 0008 + 450 | 450 | 0009 + 500 | 500 | 0010 + 550 | 550 | 0011 +(12 rows) + +SELECT t1.* FROM uplt1 t1 WHERE t1.c IN (SELECT t1.c FROM uplt2 t1 WHERE t1.c IN (SELECT ltrim(t1.c, 'A') FROM uplt1_e t1 WHERE t1.a % 25 = 0)) AND t1.a % 25 = 0 ORDER BY t1.a; + a | b | c +-----+-----+------ + 0 | 0 | 0000 + 50 | 50 | 0001 + 100 | 100 | 0002 + 150 | 150 | 0003 + 200 | 200 | 0004 + 250 | 250 | 0005 + 300 | 300 | 0006 + 350 | 350 | 0007 + 400 | 400 | 0008 + 450 | 450 | 0009 + 500 | 500 | 0010 + 550 | 550 | 0011 +(12 rows) + +-- +-- negative testcases +-- +-- joins where one of the relations is proven empty +EXPLAIN (VERBOSE, COSTS OFF) +SELECT t1.a, t1.c, t2.b, t2.c FROM prt1 t1, prt2 t2 WHERE t1.a = t2.b AND t1.a = 1 AND t1.a = 2; + QUERY PLAN +---------------------------------- + Result + Output: t1.a, t1.c, t2.b, t2.c + One-Time Filter: false +(3 rows) + +EXPLAIN (VERBOSE, COSTS OFF) +SELECT t1.a, t1.c, t2.b, t2.c FROM (SELECT * FROM prt1 WHERE a = 1 AND a = 2) t1 LEFT JOIN prt2 t2 ON t1.a = t2.b; + QUERY PLAN +-------------------------------------- + Result + Output: prt1.a, prt1.c, t2.b, t2.c + One-Time Filter: false +(3 rows) + +EXPLAIN (VERBOSE, COSTS OFF) +SELECT t1.a, t1.c, t2.b, t2.c FROM (SELECT * FROM prt1 WHERE a = 1 AND a = 2) t1 RIGHT JOIN prt2 t2 ON t1.a = t2.b WHERE t2.a % 25 = 0 ORDER BY t1.a, t2.b; + QUERY PLAN +--------------------------------------------------- + Sort + Output: a, c, t2.b, t2.c + Sort Key: a, t2.b + -> Hash Left Join + Output: a, c, t2.b, t2.c + Hash Cond: (t2.b = a) + -> Append + -> Seq Scan on public.prt2 t2 + Output: t2.b, t2.c + Filter: ((t2.a % 25) = 0) + -> Seq Scan on public.prt2_p1 t2_1 + Output: t2_1.b, t2_1.c + Filter: ((t2_1.a % 25) = 0) + -> Seq Scan on public.prt2_p2 t2_2 + Output: t2_2.b, t2_2.c + Filter: ((t2_2.a % 25) = 0) + -> Seq Scan on public.prt2_p3 t2_3 + Output: t2_3.b, t2_3.c + Filter: ((t2_3.a % 25) = 0) + -> Hash + Output: a, c + -> Result + Output: a, c + One-Time Filter: false +(24 rows) + +EXPLAIN (VERBOSE, COSTS OFF) +SELECT t1.a, t1.c, t2.b, t2.c FROM (SELECT * FROM prt1 WHERE a = 1 AND a = 2) t1 FULL JOIN prt2 t2 ON t1.a = t2.b WHERE t2.a % 25 = 0 ORDER BY t1.a, t2.b; + QUERY PLAN +--------------------------------------------------- + Sort + Output: a, c, t2.b, t2.c + Sort Key: a, t2.b + -> Hash Left Join + Output: a, c, t2.b, t2.c + Hash Cond: (t2.b = a) + -> Append + -> Seq Scan on public.prt2 t2 + Output: t2.b, t2.c + Filter: ((t2.a % 25) = 0) + -> Seq Scan on public.prt2_p1 t2_1 + Output: t2_1.b, t2_1.c + Filter: ((t2_1.a % 25) = 0) + -> Seq Scan on public.prt2_p2 t2_2 + Output: t2_2.b, t2_2.c + Filter: ((t2_2.a % 25) = 0) + -> Seq Scan on public.prt2_p3 t2_3 + Output: t2_3.b, t2_3.c + Filter: ((t2_3.a % 25) = 0) + -> Hash + Output: a, c + -> Result + Output: a, c + One-Time Filter: false +(24 rows) + +CREATE TABLE prt1_n (a int, b int, c varchar) PARTITION BY RANGE(c); +CREATE TABLE prt1_n_p1 PARTITION OF prt1_n FOR VALUES FROM ('0000') TO ('0250'); +CREATE TABLE prt1_n_p2 PARTITION OF prt1_n FOR VALUES FROM ('0250') TO ('0500'); +INSERT INTO prt1_n SELECT i, i, to_char(i, 'FM0000') FROM generate_series(0, 499, 2) i; +ANALYZE prt1_n; +ANALYZE prt1_n_p1; +ANALYZE prt1_n_p2; +CREATE TABLE prt2_n (a int, b int, c text) PARTITION BY LIST(c); +CREATE TABLE prt2_n_p1 PARTITION OF prt2_n FOR VALUES IN ('0000', '0003', '0004', '0010', '0006', '0007'); +CREATE TABLE prt2_n_p2 PARTITION OF prt2_n FOR VALUES IN ('0001', '0005', '0002', '0009', '0008', '0011'); +INSERT INTO prt2_n SELECT i, i, to_char(i/50, 'FM0000') FROM generate_series(0, 599, 2) i; +ANALYZE prt2_n; +ANALYZE prt2_n_p1; +ANALYZE prt2_n_p2; +CREATE TABLE prt3_n (a int, b int, c text) PARTITION BY LIST(c); +CREATE TABLE prt3_n_p1 PARTITION OF prt3_n FOR VALUES IN ('0000', '0004', '0006', '0007'); +CREATE TABLE prt3_n_p2 PARTITION OF prt3_n FOR VALUES IN ('0001', '0002', '0008', '0010'); +CREATE TABLE prt3_n_p3 PARTITION OF prt3_n FOR VALUES IN ('0003', '0005', '0009', '0011'); +INSERT INTO prt2_n SELECT i, i, to_char(i/50, 'FM0000') FROM generate_series(0, 599, 2) i; +ANALYZE prt3_n; +ANALYZE prt3_n_p1; +ANALYZE prt3_n_p2; +ANALYZE prt3_n_p3; +CREATE TABLE prt4_n (a int, b int, c text) PARTITION BY RANGE(a); +CREATE TABLE prt4_n_p1 PARTITION OF prt4_n FOR VALUES FROM (0) TO (300); +CREATE TABLE prt4_n_p2 PARTITION OF prt4_n FOR VALUES FROM (300) TO (500); +CREATE TABLE prt4_n_p3 PARTITION OF prt4_n FOR VALUES FROM (500) TO (600); +INSERT INTO prt4_n SELECT i, i, to_char(i, 'FM0000') FROM generate_series(0, 599, 2) i; +ANALYZE prt4_n; +ANALYZE prt4_n_p1; +ANALYZE prt4_n_p2; +ANALYZE prt4_n_p3; +-- partition-wise join can not be applied if the partition ranges differ +EXPLAIN (COSTS OFF) +SELECT t1.a, t1.c, t2.b, t2.c FROM prt1 t1, prt4_n t2 WHERE t1.a = t2.a; + QUERY PLAN +---------------------------------------------- + Hash Join + Hash Cond: (t1.a = t2.a) + -> Append + -> Seq Scan on prt1 t1 + -> Seq Scan on prt1_p1 t1_1 + -> Seq Scan on prt1_p3 t1_2 + -> Seq Scan on prt1_p2 t1_3 + -> Hash + -> Append + -> Seq Scan on prt4_n t2 + -> Seq Scan on prt4_n_p1 t2_1 + -> Seq Scan on prt4_n_p2 t2_2 + -> Seq Scan on prt4_n_p3 t2_3 +(13 rows) + +EXPLAIN (COSTS OFF) +SELECT t1.a, t1.c, t2.b, t2.c FROM prt1 t1 FULL JOIN prt4_n t2 ON t1.a = t2.a; + QUERY PLAN +---------------------------------------------- + Hash Full Join + Hash Cond: (t1.a = t2.a) + -> Append + -> Seq Scan on prt1 t1 + -> Seq Scan on prt1_p1 t1_1 + -> Seq Scan on prt1_p3 t1_2 + -> Seq Scan on prt1_p2 t1_3 + -> Hash + -> Append + -> Seq Scan on prt4_n t2 + -> Seq Scan on prt4_n_p1 t2_1 + -> Seq Scan on prt4_n_p2 t2_2 + -> Seq Scan on prt4_n_p3 t2_3 +(13 rows) + +-- partition-wise join can not be applied if there are no equi-join conditions +-- between partition keys +EXPLAIN (COSTS OFF) +SELECT t1.a, t1.c, t2.b, t2.c FROM prt1 t1 LEFT JOIN prt2 t2 ON (t1.a < t2.b); + QUERY PLAN +--------------------------------------------------------- + Nested Loop Left Join + -> Append + -> Seq Scan on prt1 t1 + -> Seq Scan on prt1_p1 t1_1 + -> Seq Scan on prt1_p3 t1_2 + -> Seq Scan on prt1_p2 t1_3 + -> Append + -> Seq Scan on prt2 t2 + Filter: (t1.a < b) + -> Index Scan using iprt2_p1_b on prt2_p1 t2_1 + Index Cond: (t1.a < b) + -> Index Scan using iprt2_p2_b on prt2_p2 t2_2 + Index Cond: (t1.a < b) + -> Index Scan using iprt2_p3_b on prt2_p3 t2_3 + Index Cond: (t1.a < b) +(15 rows) + +-- equi-join with join condition on partial keys does not qualify for +-- partition-wise join +EXPLAIN (COSTS OFF) +SELECT t1.a, t1.c, t2.b, t2.c FROM prt1_m t1, prt2_m t2 WHERE t1.a = (t2.b + t2.a)/2 AND t1.a % 25 = 0; + QUERY PLAN +---------------------------------------------- + Hash Join + Hash Cond: (((t2.b + t2.a) / 2) = t1.a) + -> Append + -> Seq Scan on prt2_m t2 + -> Seq Scan on prt2_m_p1 t2_1 + -> Seq Scan on prt2_m_p2 t2_2 + -> Seq Scan on prt2_m_p3 t2_3 + -> Hash + -> Append + -> Seq Scan on prt1_m t1 + Filter: ((a % 25) = 0) + -> Seq Scan on prt1_m_p1 t1_1 + Filter: ((a % 25) = 0) + -> Seq Scan on prt1_m_p2 t1_2 + Filter: ((a % 25) = 0) + -> Seq Scan on prt1_m_p3 t1_3 + Filter: ((a % 25) = 0) +(17 rows) + +-- equi-join between out-of-order partition key columns does not qualify for +-- partition-wise join +EXPLAIN (COSTS OFF) +SELECT t1.a, t1.c, t2.b, t2.c FROM prt1_m t1 LEFT JOIN prt2_m t2 ON t1.a = t2.b WHERE t1.a % 25 = 0; + QUERY PLAN +---------------------------------------------- + Hash Right Join + Hash Cond: (t2.b = t1.a) + -> Append + -> Seq Scan on prt2_m t2 + -> Seq Scan on prt2_m_p1 t2_1 + -> Seq Scan on prt2_m_p2 t2_2 + -> Seq Scan on prt2_m_p3 t2_3 + -> Hash + -> Append + -> Seq Scan on prt1_m t1 + Filter: ((a % 25) = 0) + -> Seq Scan on prt1_m_p1 t1_1 + Filter: ((a % 25) = 0) + -> Seq Scan on prt1_m_p2 t1_2 + Filter: ((a % 25) = 0) + -> Seq Scan on prt1_m_p3 t1_3 + Filter: ((a % 25) = 0) +(17 rows) + +-- equi-join between non-key columns does not qualify for partition-wise join +EXPLAIN (COSTS OFF) +SELECT t1.a, t1.c, t2.b, t2.c FROM prt1_m t1 LEFT JOIN prt2_m t2 ON t1.c = t2.c WHERE t1.a % 25 = 0; + QUERY PLAN +---------------------------------------------- + Hash Right Join + Hash Cond: ((t2.c)::text = (t1.c)::text) + -> Append + -> Seq Scan on prt2_m t2 + -> Seq Scan on prt2_m_p1 t2_1 + -> Seq Scan on prt2_m_p2 t2_2 + -> Seq Scan on prt2_m_p3 t2_3 + -> Hash + -> Append + -> Seq Scan on prt1_m t1 + Filter: ((a % 25) = 0) + -> Seq Scan on prt1_m_p1 t1_1 + Filter: ((a % 25) = 0) + -> Seq Scan on prt1_m_p2 t1_2 + Filter: ((a % 25) = 0) + -> Seq Scan on prt1_m_p3 t1_3 + Filter: ((a % 25) = 0) +(17 rows) + +-- partition-wise join can not be applied for a join between list and range +-- partitioned table +EXPLAIN (COSTS OFF) +SELECT t1.a, t1.c, t2.b, t2.c FROM prt1_n t1, prt2_n t2 WHERE t1.c = t2.c; + QUERY PLAN +---------------------------------------------- + Hash Join + Hash Cond: (t2.c = (t1.c)::text) + -> Append + -> Seq Scan on prt2_n t2 + -> Seq Scan on prt2_n_p1 t2_1 + -> Seq Scan on prt2_n_p2 t2_2 + -> Hash + -> Append + -> Seq Scan on prt1_n t1 + -> Seq Scan on prt1_n_p1 t1_1 + -> Seq Scan on prt1_n_p2 t1_2 +(11 rows) + +EXPLAIN (COSTS OFF) +SELECT t1.a, t1.c, t2.b, t2.c FROM prt1_n t1 LEFT JOIN prt2_n t2 ON (t1.c = t2.c); + QUERY PLAN +---------------------------------------------- + Hash Right Join + Hash Cond: (t2.c = (t1.c)::text) + -> Append + -> Seq Scan on prt2_n t2 + -> Seq Scan on prt2_n_p1 t2_1 + -> Seq Scan on prt2_n_p2 t2_2 + -> Hash + -> Append + -> Seq Scan on prt1_n t1 + -> Seq Scan on prt1_n_p1 t1_1 + -> Seq Scan on prt1_n_p2 t1_2 +(11 rows) + +-- partition-wise join can not be applied between tables with different +-- partition lists +EXPLAIN (COSTS OFF) +SELECT t1.a, t1.c, t2.b, t2.c FROM prt1_n t1 RIGHT JOIN prt1 t2 ON (t1.c = t2.c); + QUERY PLAN +---------------------------------------------- + Hash Left Join + Hash Cond: ((t2.c)::text = (t1.c)::text) + -> Append + -> Seq Scan on prt1 t2 + -> Seq Scan on prt1_p1 t2_1 + -> Seq Scan on prt1_p3 t2_2 + -> Seq Scan on prt1_p2 t2_3 + -> Hash + -> Append + -> Seq Scan on prt1_n t1 + -> Seq Scan on prt1_n_p1 t1_1 + -> Seq Scan on prt1_n_p2 t1_2 +(12 rows) + +EXPLAIN (COSTS OFF) +SELECT t1.a, t1.c, t2.b, t2.c FROM prt1_n t1 FULL JOIN prt1 t2 ON (t1.c = t2.c); + QUERY PLAN +---------------------------------------------- + Hash Full Join + Hash Cond: ((t2.c)::text = (t1.c)::text) + -> Append + -> Seq Scan on prt1 t2 + -> Seq Scan on prt1_p1 t2_1 + -> Seq Scan on prt1_p3 t2_2 + -> Seq Scan on prt1_p2 t2_3 + -> Hash + -> Append + -> Seq Scan on prt1_n t1 + -> Seq Scan on prt1_n_p1 t1_1 + -> Seq Scan on prt1_n_p2 t1_2 +(12 rows) + diff --git a/src/test/regress/parallel_schedule b/src/test/regress/parallel_schedule index edeb2d6..ac38f50 100644 --- a/src/test/regress/parallel_schedule +++ b/src/test/regress/parallel_schedule @@ -103,7 +103,7 @@ test: publication subscription # ---------- # Another group of parallel tests # ---------- -test: select_views portals_p2 foreign_key cluster dependency guc bitmapops combocid tsearch tsdicts foreign_data window xmlmap functional_deps advisory_lock json jsonb json_encoding indirect_toast equivclass +test: select_views portals_p2 foreign_key cluster dependency guc bitmapops combocid tsearch tsdicts foreign_data window xmlmap functional_deps advisory_lock json jsonb json_encoding indirect_toast equivclass partition_join # ---------- # Another group of parallel tests # NB: temp.sql does a reconnect which transiently uses 2 connections, diff --git a/src/test/regress/serial_schedule b/src/test/regress/serial_schedule index 27a46d7..1bf98a4 100644 --- a/src/test/regress/serial_schedule +++ b/src/test/regress/serial_schedule @@ -172,3 +172,4 @@ test: with test: xml test: event_trigger test: stats +test: partition_join diff --git a/src/test/regress/sql/partition_join.sql b/src/test/regress/sql/partition_join.sql new file mode 100644 index 0000000..0322f1e --- /dev/null +++ b/src/test/regress/sql/partition_join.sql @@ -0,0 +1,515 @@ +-- +-- PARTITION_JOIN +-- Test partition-wise join between partitioned tables +-- + +-- +-- partitioned by a single column +-- +CREATE TABLE prt1 (a int, b int, c varchar) PARTITION BY RANGE(a); +CREATE TABLE prt1_p1 PARTITION OF prt1 FOR VALUES FROM (0) TO (250); +CREATE TABLE prt1_p3 PARTITION OF prt1 FOR VALUES FROM (500) TO (600); +CREATE TABLE prt1_p2 PARTITION OF prt1 FOR VALUES FROM (250) TO (500); +INSERT INTO prt1 SELECT i, i, to_char(i, 'FM0000') FROM generate_series(0, 599, 2) i; +ANALYZE prt1; +ANALYZE prt1_p1; +ANALYZE prt1_p2; +ANALYZE prt1_p3; +-- TODO: This table is created only for testing the results. Remove once +-- results are tested. +CREATE TABLE uprt1 AS SELECT * FROM prt1; + +CREATE TABLE prt2 (a int, b int, c varchar) PARTITION BY RANGE(b); +CREATE TABLE prt2_p1 PARTITION OF prt2 FOR VALUES FROM (0) TO (250); +CREATE TABLE prt2_p2 PARTITION OF prt2 FOR VALUES FROM (250) TO (500); +CREATE TABLE prt2_p3 PARTITION OF prt2 FOR VALUES FROM (500) TO (600); +INSERT INTO prt2 SELECT i, i, to_char(i, 'FM0000') FROM generate_series(0, 599, 3) i; +-- TODO: This table is created only for testing the results. Remove once +-- results are tested. +ANALYZE prt2; +ANALYZE prt2_p1; +ANALYZE prt2_p2; +ANALYZE prt2_p3; +CREATE TABLE uprt2 AS SELECT * FROM prt2; + +-- inner join +EXPLAIN (VERBOSE, COSTS OFF) +SELECT t1.a, t1.c, t2.b, t2.c FROM prt1 t1, prt2 t2 WHERE t1.a = t2.b AND t1.a % 25 = 0 ORDER BY t1.a, t2.b; +SELECT t1.a, t1.c, t2.b, t2.c FROM prt1 t1, prt2 t2 WHERE t1.a = t2.b AND t1.a % 25 = 0 ORDER BY t1.a, t2.b; +SELECT t1.a, t1.c, t2.b, t2.c FROM uprt1 t1, uprt2 t2 WHERE t1.a = t2.b AND t1.a % 25 = 0 ORDER BY t1.a, t2.b; + +-- left outer join +EXPLAIN (VERBOSE, COSTS OFF) +SELECT t1.a, t1.c, t2.b, t2.c FROM prt1 t1 LEFT JOIN prt2 t2 ON t1.a = t2.b WHERE t1.a % 25 = 0 ORDER BY t1.a, t2.b; +SELECT t1.a, t1.c, t2.b, t2.c FROM prt1 t1 LEFT JOIN prt2 t2 ON t1.a = t2.b WHERE t1.a % 25 = 0 ORDER BY t1.a, t2.b; +SELECT t1.a, t1.c, t2.b, t2.c FROM uprt1 t1 LEFT JOIN uprt2 t2 ON t1.a = t2.b WHERE t1.a % 25 = 0 ORDER BY t1.a, t2.b; + +-- right outer join +EXPLAIN (VERBOSE, COSTS OFF) +SELECT t1.a, t1.c, t2.b, t2.c FROM prt1 t1 RIGHT JOIN prt2 t2 ON t1.a = t2.b WHERE t2.b % 25 = 0 ORDER BY t1.a, t2.b; +SELECT t1.a, t1.c, t2.b, t2.c FROM prt1 t1 RIGHT JOIN prt2 t2 ON t1.a = t2.b WHERE t2.b % 25 = 0 ORDER BY t1.a, t2.b; +SELECT t1.a, t1.c, t2.b, t2.c FROM uprt1 t1 RIGHT JOIN uprt2 t2 ON t1.a = t2.b WHERE t2.b % 25 = 0 ORDER BY t1.a, t2.b; + +-- full outer join +EXPLAIN (VERBOSE, COSTS OFF) +SELECT t1.a, t1.c, t2.b, t2.c FROM (SELECT * FROM prt1 WHERE prt1.a % 25 = 0) t1 FULL JOIN (SELECT * FROM prt2 WHERE prt2.b % 25 = 0) t2 ON (t1.a = t2.b) ORDER BY t1.a, t2.b; +SELECT t1.a, t1.c, t2.b, t2.c FROM (SELECT * FROM prt1 WHERE prt1.a % 25 = 0) t1 FULL JOIN (SELECT * FROM prt2 WHERE prt2.b % 25 = 0) t2 ON (t1.a = t2.b) ORDER BY t1.a, t2.b; +SELECT t1.a, t1.c, t2.b, t2.c FROM (SELECT * FROM uprt1 t1 WHERE t1.a % 25 = 0) t1 FULL JOIN (SELECT * FROM uprt2 t2 WHERE t2.b % 25 = 0) t2 ON (t1.a = t2.b) ORDER BY t1.a, t2.b; + +-- Cases with non-nullable expressions in subquery results; +-- make sure these go to null as expected +EXPLAIN (VERBOSE, COSTS OFF) +SELECT t1.a, t1.c, t2.b, t2.c FROM (SELECT 50 phv, * FROM prt1 WHERE prt1.a % 25 = 0) t1 FULL JOIN (SELECT 75 phv, * FROM prt2 WHERE prt2.b % 25 = 0) t2 ON (t1.a = t2.b) WHERE t1.phv = t1.b OR t2.phv = t2.b ORDER BY t1.a, t2.b; +SELECT t1.a, t1.c, t2.b, t2.c FROM (SELECT 50 phv, * FROM prt1 WHERE prt1.a % 25 = 0) t1 FULL JOIN (SELECT 75 phv, * FROM prt2 WHERE prt2.b % 25 = 0) t2 ON (t1.a = t2.b) WHERE t1.phv = t1.b OR t2.phv = t2.b ORDER BY t1.a, t2.b; +SELECT t1.a, t1.c, t2.b, t2.c FROM (SELECT 50 phv, * FROM uprt1 WHERE uprt1.a % 25 = 0) t1 FULL JOIN (SELECT 75 phv, * FROM uprt2 WHERE uprt2.b % 25 = 0) t2 ON (t1.a = t2.b) WHERE t1.phv = t1.b OR t2.phv = t2.b ORDER BY t1.a, t2.b; + +EXPLAIN (VERBOSE, COSTS OFF) +SELECT t1.a, t1.c, t1.phv, t2.b, t2.c, t2.phv FROM (SELECT 25 phv, * FROM prt1 WHERE prt1.a % 25 = 0) t1 FULL JOIN (SELECT 50 phv, * FROM prt2 WHERE prt2.b % 25 = 0) t2 ON (t1.a = t2.b) ORDER BY t1.a, t2.b; +SELECT t1.a, t1.c, t1.phv, t2.b, t2.c, t2.phv FROM (SELECT 25 phv, * FROM prt1 WHERE prt1.a % 25 = 0) t1 FULL JOIN (SELECT 50 phv, * FROM prt2 WHERE prt2.b % 25 = 0) t2 ON (t1.a = t2.b) ORDER BY t1.a, t2.b; +SELECT t1.a, t1.c, t1.phv, t2.b, t2.c, t2.phv FROM (SELECT 25 phv, * FROM uprt1 WHERE uprt1.a % 25 = 0) t1 FULL JOIN (SELECT 50 phv, * FROM uprt2 WHERE uprt2.b % 25 = 0) t2 ON (t1.a = t2.b) ORDER BY t1.a, t2.b; + +-- Join with pruned partitions from joining relations +EXPLAIN (VERBOSE, COSTS OFF) +SELECT t1.a, t1.c, t2.b, t2.c FROM prt1 t1, prt2 t2 WHERE t1.a = t2.b AND t1.a < 450 AND t2.b > 250 AND t1.a % 25 = 0 ORDER BY t1.a, t2.b; +SELECT t1.a, t1.c, t2.b, t2.c FROM prt1 t1, prt2 t2 WHERE t1.a = t2.b AND t1.a < 450 AND t2.b > 250 AND t1.a % 25 = 0 ORDER BY t1.a, t2.b; +SELECT t1.a, t1.c, t2.b, t2.c FROM uprt1 t1, uprt2 t2 WHERE t1.a = t2.b AND t1.a < 450 AND t2.b > 250 AND t1.a % 25 = 0 ORDER BY t1.a, t2.b; + +EXPLAIN (VERBOSE, COSTS OFF) +SELECT t1.a, t1.c, t2.b, t2.c FROM (SELECT * FROM prt1 WHERE a < 450) t1 LEFT JOIN (SELECT * FROM prt2 WHERE b > 250) t2 ON t1.a = t2.b WHERE t1.a % 25 = 0 ORDER BY t1.a, t2.b; +SELECT t1.a, t1.c, t2.b, t2.c FROM (SELECT * FROM prt1 WHERE a < 450) t1 LEFT JOIN (SELECT * FROM prt2 WHERE b > 250) t2 ON t1.a = t2.b WHERE t1.a % 25 = 0 ORDER BY t1.a, t2.b; +SELECT t1.a, t1.c, t2.b, t2.c FROM (SELECT * FROM uprt1 WHERE a < 450) t1 LEFT JOIN (SELECT * FROM uprt2 WHERE b > 250) t2 ON t1.a = t2.b WHERE t1.a % 25 = 0 ORDER BY t1.a, t2.b; + +EXPLAIN (VERBOSE, COSTS OFF) +SELECT t1.a, t1.c, t2.b, t2.c FROM (SELECT * FROM prt1 WHERE a < 450) t1 RIGHT JOIN (SELECT * FROM prt2 WHERE b > 250) t2 ON t1.a = t2.b WHERE t2.a % 25 = 0 ORDER BY t1.a, t2.b; +SELECT t1.a, t1.c, t2.b, t2.c FROM (SELECT * FROM prt1 WHERE a < 450) t1 RIGHT JOIN (SELECT * FROM prt2 WHERE b > 250) t2 ON t1.a = t2.b WHERE t2.a % 25 = 0 ORDER BY t1.a, t2.b; +SELECT t1.a, t1.c, t2.b, t2.c FROM (SELECT * FROM uprt1 WHERE a < 450) t1 RIGHT JOIN (SELECT * FROM uprt2 WHERE b > 250) t2 ON t1.a = t2.b WHERE t2.a % 25 = 0 ORDER BY t1.a, t2.b; + +EXPLAIN (VERBOSE, COSTS OFF) +SELECT t1.a, t1.c, t2.b, t2.c FROM (SELECT * FROM prt1 WHERE a < 450 AND a % 25 = 0) t1 FULL JOIN (SELECT * FROM prt2 WHERE b > 250 AND b % 25 = 0) t2 ON t1.a = t2.b ORDER BY t1.a, t2.b; +SELECT t1.a, t1.c, t2.b, t2.c FROM (SELECT * FROM prt1 WHERE a < 450 AND a % 25 = 0) t1 FULL JOIN (SELECT * FROM prt2 WHERE b > 250 AND b % 25 = 0) t2 ON t1.a = t2.b ORDER BY t1.a, t2.b; +SELECT t1.a, t1.c, t2.b, t2.c FROM (SELECT * FROM uprt1 WHERE a < 450 AND a % 25 = 0) t1 FULL JOIN (SELECT * FROM uprt2 WHERE b > 250 AND b % 25 = 0) t2 ON t1.a = t2.b ORDER BY t1.a, t2.b; + +-- Semi-join +EXPLAIN (VERBOSE, COSTS OFF) +SELECT t1.* FROM prt1 t1 WHERE t1.a IN (SELECT t1.b FROM prt2 t1 WHERE t1.b % 25 = 0) AND t1.a % 25 = 0 ORDER BY t1.a; +SELECT t1.* FROM prt1 t1 WHERE t1.a IN (SELECT t1.b FROM prt2 t1 WHERE t1.b % 25 = 0) AND t1.a % 25 = 0 ORDER BY t1.a; +SELECT t1.* FROM uprt1 t1 WHERE t1.a IN (SELECT t1.b FROM uprt2 t1 WHERE t1.b % 25 = 0) AND t1.a % 25 = 0 ORDER BY t1.a; + +-- lateral reference +EXPLAIN (VERBOSE, COSTS OFF) +SELECT * FROM prt1 t1 LEFT JOIN LATERAL + (SELECT t2.a AS t2a, t3.a AS t3a, least(t1.a,t2.a,t3.a) FROM prt1 t2 JOIN prt2 t3 ON (t2.a = t3.b)) ss + ON t1.a = ss.t2a WHERE t1.a % 25 = 0 ORDER BY t1.a; +SELECT * FROM prt1 t1 LEFT JOIN LATERAL + (SELECT t2.a AS t2a, t3.a AS t3a, least(t1.a,t2.a,t3.a) FROM prt1 t2 JOIN prt2 t3 ON (t2.a = t3.b)) ss + ON t1.a = ss.t2a WHERE t1.a % 25 = 0 ORDER BY t1.a; +SELECT * FROM uprt1 t1 LEFT JOIN LATERAL + (SELECT t2.a AS t2a, t3.a AS t3a, least(t1.a,t2.a,t3.a) FROM uprt1 t2 JOIN uprt2 t3 ON (t2.a = t3.b)) ss + ON t1.a = ss.t2a WHERE t1.a % 25 = 0 ORDER BY t1.a; + +EXPLAIN (VERBOSE, COSTS OFF) +SELECT * FROM prt1 t1 LEFT JOIN LATERAL + (SELECT t2.a AS t2a, t3.a AS t3a, least(t1.a,t2.a,t3.a) FROM prt1 t2 JOIN prt2 t3 ON (t2.a = t3.b)) ss + ON t1.b = ss.t2a WHERE t1.a % 25 = 0 ORDER BY t1.a; +SELECT * FROM prt1 t1 LEFT JOIN LATERAL + (SELECT t2.a AS t2a, t3.a AS t3a, least(t1.a,t2.a,t3.a) FROM prt1 t2 JOIN prt2 t3 ON (t2.a = t3.b)) ss + ON t1.b = ss.t2a WHERE t1.a % 25 = 0 ORDER BY t1.a; +SELECT * FROM uprt1 t1 LEFT JOIN LATERAL + (SELECT t2.a AS t2a, t3.a AS t3a, least(t1.a,t2.a,t3.a) FROM uprt1 t2 JOIN uprt2 t3 ON (t2.a = t3.b)) ss + ON t1.b = ss.t2a WHERE t1.a % 25 = 0 ORDER BY t1.a; + +-- +-- partitioned by expression +-- +CREATE TABLE prt1_e (a int, b int, c varchar) PARTITION BY RANGE(((a + b)/2)); +CREATE TABLE prt1_e_p1 PARTITION OF prt1_e FOR VALUES FROM (0) TO (250); +CREATE TABLE prt1_e_p2 PARTITION OF prt1_e FOR VALUES FROM (250) TO (500); +CREATE TABLE prt1_e_p3 PARTITION OF prt1_e FOR VALUES FROM (500) TO (600); +INSERT INTO prt1_e SELECT i, i, to_char(i, 'FM0000') FROM generate_series(0, 599, 2) i; +ANALYZE prt1_e; +ANALYZE prt1_e_p1; +ANALYZE prt1_e_p2; +ANALYZE prt1_e_p3; +-- TODO: This table is created only for testing the results. Remove once +-- results are tested. +CREATE TABLE uprt1_e AS SELECT * FROM prt1_e; + +CREATE TABLE prt2_e (a int, b int, c varchar) PARTITION BY RANGE(((b + a)/2)); +CREATE TABLE prt2_e_p1 PARTITION OF prt2_e FOR VALUES FROM (0) TO (250); +CREATE TABLE prt2_e_p2 PARTITION OF prt2_e FOR VALUES FROM (250) TO (500); +CREATE TABLE prt2_e_p3 PARTITION OF prt2_e FOR VALUES FROM (500) TO (600); +INSERT INTO prt2_e SELECT i, i, to_char(i, 'FM0000') FROM generate_series(0, 599, 3) i; +ANALYZE prt2_e; +ANALYZE prt2_e_p1; +ANALYZE prt2_e_p2; +ANALYZE prt2_e_p3; +-- TODO: This table is created only for testing the results. Remove once +-- results are tested. +CREATE TABLE uprt2_e AS SELECT * FROM prt2_e; + +EXPLAIN (VERBOSE, COSTS OFF) +SELECT t1.a, t1.c, t2.b, t2.c FROM prt1_e t1, prt2_e t2 WHERE (t1.a + t1.b)/2 = (t2.b + t2.a)/2 AND t1.a % 25 = 0 ORDER BY t1.a, t2.b; +SELECT t1.a, t1.c, t2.b, t2.c FROM prt1_e t1, prt2_e t2 WHERE (t1.a + t1.b)/2 = (t2.b + t2.a)/2 AND t1.a % 25 = 0 ORDER BY t1.a, t2.b; +SELECT t1.a, t1.c, t2.b, t2.c FROM uprt1_e t1, uprt2_e t2 WHERE (t1.a + t1.b)/2 = (t2.b + t2.a)/2 AND t1.a % 25 = 0 ORDER BY t1.a, t2.b; + +EXPLAIN (VERBOSE, COSTS OFF) +SELECT t1.a, t1.c, t2.b, t2.c FROM prt1_e t1 LEFT JOIN prt2_e t2 ON (t1.a + t1.b)/2 = (t2.b + t2.a)/2 WHERE t1.a % 25 = 0 ORDER BY t1.a, t2.b; +SELECT t1.a, t1.c, t2.b, t2.c FROM prt1_e t1 LEFT JOIN prt2_e t2 ON (t1.a + t1.b)/2 = (t2.b + t2.a)/2 WHERE t1.a % 25 = 0 ORDER BY t1.a, t2.b; +SELECT t1.a, t1.c, t2.b, t2.c FROM uprt1_e t1 LEFT JOIN uprt2_e t2 ON (t1.a + t1.b)/2 = (t2.b + t2.a)/2 WHERE t1.a % 25 = 0 ORDER BY t1.a, t2.b; + +-- +-- N-way join +-- +EXPLAIN (VERBOSE, COSTS OFF) +SELECT t1.a, t1.c, t2.b, t2.c, t3.a + t3.b, t3.c FROM prt1 t1, prt2 t2, prt1_e t3 WHERE t1.a = t2.b AND t1.a = (t3.a + t3.b)/2 AND t1.a % 25 = 0 ORDER BY t1.a, t2.b; +SELECT t1.a, t1.c, t2.b, t2.c, t3.a + t3.b, t3.c FROM prt1 t1, prt2 t2, prt1_e t3 WHERE t1.a = t2.b AND t1.a = (t3.a + t3.b)/2 AND t1.a % 25 = 0 ORDER BY t1.a, t2.b; +SELECT t1.a, t1.c, t2.b, t2.c, t3.a + t3.b, t3.c FROM uprt1 t1, uprt2 t2, uprt1_e t3 WHERE t1.a = t2.b AND t1.a = (t3.a + t3.b)/2 AND t1.a % 25 = 0 ORDER BY t1.a, t2.b; + +EXPLAIN (VERBOSE, COSTS OFF) +SELECT t1.a, t1.c, t2.b, t2.c, t3.a + t3.b, t3.c FROM (prt1 t1 LEFT JOIN prt2 t2 ON t1.a = t2.b) LEFT JOIN prt1_e t3 ON (t1.a = (t3.a + t3.b)/2) WHERE t1.a % 25 = 0 ORDER BY t1.a, t2.b, t3.a + t3.b; +SELECT t1.a, t1.c, t2.b, t2.c, t3.a + t3.b, t3.c FROM (prt1 t1 LEFT JOIN prt2 t2 ON t1.a = t2.b) LEFT JOIN prt1_e t3 ON (t1.a = (t3.a + t3.b)/2) WHERE t1.a % 25 = 0 ORDER BY t1.a, t2.b, t3.a + t3.b; +SELECT t1.a, t1.c, t2.b, t2.c, t3.a + t3.b, t3.c FROM (uprt1 t1 LEFT JOIN uprt2 t2 ON t1.a = t2.b) LEFT JOIN uprt1_e t3 ON (t1.a = (t3.a + t3.b)/2) WHERE t1.a % 25 = 0 ORDER BY t1.a, t2.b, t3.a + t3.b; + +EXPLAIN (VERBOSE, COSTS OFF) +SELECT t1.a, t1.c, t2.b, t2.c, t3.a + t3.b, t3.c FROM (prt1 t1 LEFT JOIN prt2 t2 ON t1.a = t2.b) LEFT JOIN prt1_e t3 ON (t2.b = (t3.a + t3.b)/2) WHERE t1.a % 25 = 0 ORDER BY t1.a, t2.b, t3.a + t3.b; +SELECT t1.a, t1.c, t2.b, t2.c, t3.a + t3.b, t3.c FROM (prt1 t1 LEFT JOIN prt2 t2 ON t1.a = t2.b) LEFT JOIN prt1_e t3 ON (t2.b = (t3.a + t3.b)/2) WHERE t1.a % 25 = 0 ORDER BY t1.a, t2.b, t3.a + t3.b; +SELECT t1.a, t1.c, t2.b, t2.c, t3.a + t3.b, t3.c FROM (uprt1 t1 LEFT JOIN uprt2 t2 ON t1.a = t2.b) LEFT JOIN uprt1_e t3 ON (t2.b = (t3.a + t3.b)/2) WHERE t1.a % 25 = 0 ORDER BY t1.a, t2.b, t3.a + t3.b; + +EXPLAIN (VERBOSE, COSTS OFF) +SELECT t1.a, t1.c, t2.b, t2.c, t3.a + t3.b, t3.c FROM (prt1 t1 LEFT JOIN prt2 t2 ON t1.a = t2.b) RIGHT JOIN prt1_e t3 ON (t1.a = (t3.a + t3.b)/2) WHERE t3.a % 25 = 0 ORDER BY t1.a, t2.b, t3.a + t3.b; +SELECT t1.a, t1.c, t2.b, t2.c, t3.a + t3.b, t3.c FROM (prt1 t1 LEFT JOIN prt2 t2 ON t1.a = t2.b) RIGHT JOIN prt1_e t3 ON (t1.a = (t3.a + t3.b)/2) WHERE t3.a % 25 = 0 ORDER BY t1.a, t2.b, t3.a + t3.b; +SELECT t1.a, t1.c, t2.b, t2.c, t3.a + t3.b, t3.c FROM (uprt1 t1 LEFT JOIN uprt2 t2 ON t1.a = t2.b) RIGHT JOIN uprt1_e t3 ON (t1.a = (t3.a + t3.b)/2) WHERE t3.a % 25 = 0 ORDER BY t1.a, t2.b, t3.a + t3.b; + +EXPLAIN (VERBOSE, COSTS OFF) +SELECT t1.a, t1.c, t2.b, t2.c, t3.a + t3.b, t3.c FROM (prt1 t1 RIGHT JOIN prt2 t2 ON t1.a = t2.b) RIGHT JOIN prt1_e t3 ON (t2.b = (t3.a + t3.b)/2) WHERE t3.a % 25 = 0 ORDER BY t1.a, t2.b, t3.a + t3.b; +SELECT t1.a, t1.c, t2.b, t2.c, t3.a + t3.b, t3.c FROM (prt1 t1 RIGHT JOIN prt2 t2 ON t1.a = t2.b) RIGHT JOIN prt1_e t3 ON (t2.b = (t3.a + t3.b)/2) WHERE t3.a % 25 = 0 ORDER BY t1.a, t2.b, t3.a + t3.b; +SELECT t1.a, t1.c, t2.b, t2.c, t3.a + t3.b, t3.c FROM (uprt1 t1 RIGHT JOIN uprt2 t2 ON t1.a = t2.b) RIGHT JOIN uprt1_e t3 ON (t2.b = (t3.a + t3.b)/2) WHERE t3.a % 25 = 0 ORDER BY t1.a, t2.b, t3.a + t3.b; + +EXPLAIN (VERBOSE, COSTS OFF) +SELECT t1.a, t1.c, t2.b, t2.c, t3.a + t3.b, t3.c FROM ((SELECT * FROM prt1 WHERE prt1.a % 25 = 0) t1 FULL JOIN (SELECT * FROM prt2 WHERE prt2.b % 25 = 0) t2 ON (t1.a = t2.b)) FULL JOIN (SELECT * FROM prt1_e WHERE prt1_e.a % 25 = 0) t3 ON (t1.a = (t3.a + t3.b)/2) ORDER BY t1.a, t2.b, t3.a + t3.b; +SELECT t1.a, t1.c, t2.b, t2.c, t3.a + t3.b, t3.c FROM ((SELECT * FROM prt1 WHERE prt1.a % 25 = 0) t1 FULL JOIN (SELECT * FROM prt2 WHERE prt2.b % 25 = 0) t2 ON (t1.a = t2.b)) FULL JOIN (SELECT * FROM prt1_e WHERE prt1_e.a % 25 = 0) t3 ON (t1.a = (t3.a + t3.b)/2) ORDER BY t1.a, t2.b, t3.a + t3.b; +SELECT t1.a, t1.c, t2.b, t2.c, t3.a + t3.b, t3.c FROM ((SELECT * FROM uprt1 WHERE uprt1.a % 25 = 0) t1 FULL JOIN (SELECT * FROM uprt2 WHERE uprt2.b % 25 = 0) t2 ON (t1.a = t2.b)) FULL JOIN (SELECT * FROM uprt1_e WHERE uprt1_e.a % 25 = 0) t3 ON (t1.a = (t3.a + t3.b)/2) ORDER BY t1.a, t2.b, t3.a + t3.b; + +-- Cases with non-nullable expressions in subquery results; +-- make sure these go to null as expected +EXPLAIN (VERBOSE, COSTS OFF) +SELECT t1.a, t1.phv, t2.b, t2.phv, t3.a + t3.b, t3.phv FROM ((SELECT 50 phv, * FROM prt1 WHERE prt1.a % 25 = 0) t1 FULL JOIN (SELECT 75 phv, * FROM prt2 WHERE prt2.b % 25 = 0) t2 ON (t1.a = t2.b)) FULL JOIN (SELECT 50 phv, * FROM prt1_e WHERE prt1_e.a % 25 = 0) t3 ON (t1.a = (t3.a + t3.b)/2) WHERE t1.a = t1.phv OR t2.b = t2.phv OR (t3.a + t3.b)/2 = t3.phv ORDER BY t1.a, t2.b, t3.a + t3.b; +SELECT t1.a, t1.phv, t2.b, t2.phv, t3.a + t3.b, t3.phv FROM ((SELECT 50 phv, * FROM prt1 WHERE prt1.a % 25 = 0) t1 FULL JOIN (SELECT 75 phv, * FROM prt2 WHERE prt2.b % 25 = 0) t2 ON (t1.a = t2.b)) FULL JOIN (SELECT 50 phv, * FROM prt1_e WHERE prt1_e.a % 25 = 0) t3 ON (t1.a = (t3.a + t3.b)/2) WHERE t1.a = t1.phv OR t2.b = t2.phv OR (t3.a + t3.b)/2 = t3.phv ORDER BY t1.a, t2.b, t3.a + t3.b; +SELECT t1.a, t1.phv, t2.b, t2.phv, t3.a + t3.b, t3.phv FROM ((SELECT 50 phv, * FROM uprt1 WHERE uprt1.a % 25 = 0) t1 FULL JOIN (SELECT 75 phv, * FROM uprt2 WHERE uprt2.b % 25 = 0) t2 ON (t1.a = t2.b)) FULL JOIN (SELECT 50 phv, * FROM uprt1_e WHERE uprt1_e.a % 25 = 0) t3 ON (t1.a = (t3.a + t3.b)/2) WHERE t1.a = t1.phv OR t2.b = t2.phv OR (t3.a + t3.b)/2 = t3.phv ORDER BY t1.a, t2.b, t3.a + t3.b; + +-- Semi-join +EXPLAIN (VERBOSE, COSTS OFF) +SELECT t1.* FROM prt1 t1 WHERE t1.a IN (SELECT t1.b FROM prt2 t1, prt1_e t2 WHERE t1.b % 25 = 0 AND t1.b = (t2.a + t2.b)/2) AND t1.a % 25 = 0 ORDER BY t1.a; +SELECT t1.* FROM prt1 t1 WHERE t1.a IN (SELECT t1.b FROM prt2 t1, prt1_e t2 WHERE t1.b % 25 = 0 AND t1.b = (t2.a + t2.b)/2) AND t1.a % 25 = 0 ORDER BY t1.a; +SELECT t1.* FROM uprt1 t1 WHERE t1.a IN (SELECT t1.b FROM uprt2 t1, uprt1_e t2 WHERE t1.b % 25 = 0 AND t1.b = (t2.a + t2.b)/2) AND t1.a % 25 = 0 ORDER BY t1.a; + +EXPLAIN (VERBOSE, COSTS OFF) +SELECT t1.* FROM prt1 t1 WHERE t1.a IN (SELECT t1.b FROM prt2 t1 WHERE t1.b IN (SELECT (t1.a + t1.b)/2 FROM prt1_e t1 WHERE t1.a %25 = 0)) AND t1.a % 25 = 0 ORDER BY t1.a; +SELECT t1.* FROM prt1 t1 WHERE t1.a IN (SELECT t1.b FROM prt2 t1 WHERE t1.b IN (SELECT (t1.a + t1.b)/2 FROM prt1_e t1 WHERE t1.a %25 = 0)) AND t1.a % 25 = 0 ORDER BY t1.a; +SELECT t1.* FROM uprt1 t1 WHERE t1.a IN (SELECT t1.b FROM uprt2 t1 WHERE t1.b IN (SELECT (t1.a + t1.b)/2 FROM uprt1_e t1 WHERE t1.a %25 = 0)) AND t1.a % 25 = 0 ORDER BY t1.a; + +-- test merge joins with and without using indexes +SET enable_hashjoin TO off; +SET enable_nestloop TO off; + +CREATE INDEX iprt1_p1_a on prt1_p1(a); +CREATE INDEX iprt1_p2_a on prt1_p2(a); +CREATE INDEX iprt1_p3_a on prt1_p3(a); +CREATE INDEX iprt2_p1_b on prt2_p1(b); +CREATE INDEX iprt2_p2_b on prt2_p2(b); +CREATE INDEX iprt2_p3_b on prt2_p3(b); +CREATE INDEX iprt1_e_p1_ab2 on prt1_e_p1(((a+b)/2)); +CREATE INDEX iprt1_e_p2_ab2 on prt1_e_p2(((a+b)/2)); +CREATE INDEX iprt1_e_p3_ab2 on prt1_e_p3(((a+b)/2)); + +ANALYZE prt1; +ANALYZE prt1_p1; +ANALYZE prt1_p2; +ANALYZE prt1_p3; +ANALYZE prt2; +ANALYZE prt2_p1; +ANALYZE prt2_p2; +ANALYZE prt2_p3; +ANALYZE prt1_e; +ANALYZE prt1_e_p1; +ANALYZE prt1_e_p2; +ANALYZE prt1_e_p3; + +EXPLAIN (VERBOSE, COSTS OFF) +SELECT t1.a, t1.c, t2.b, t2.c, t3.a + t3.b, t3.c FROM (prt1 t1 RIGHT JOIN prt2 t2 ON t1.a = t2.b) RIGHT JOIN prt1_e t3 ON (t2.b = (t3.a + t3.b)/2) WHERE t3.a % 25 = 0 ORDER BY t1.a, t2.b, t3.a + t3.b; +SELECT t1.a, t1.c, t2.b, t2.c, t3.a + t3.b, t3.c FROM (prt1 t1 RIGHT JOIN prt2 t2 ON t1.a = t2.b) RIGHT JOIN prt1_e t3 ON (t2.b = (t3.a + t3.b)/2) WHERE t3.a % 25 = 0 ORDER BY t1.a, t2.b, t3.a + t3.b; +SELECT t1.a, t1.c, t2.b, t2.c, t3.a + t3.b, t3.c FROM (uprt1 t1 RIGHT JOIN uprt2 t2 ON t1.a = t2.b) RIGHT JOIN uprt1_e t3 ON (t2.b = (t3.a + t3.b)/2) WHERE t3.a % 25 = 0 ORDER BY t1.a, t2.b, t3.a + t3.b; + +EXPLAIN (VERBOSE, COSTS OFF) +SELECT t1.* FROM prt1 t1 WHERE t1.a IN (SELECT t1.b FROM prt2 t1 WHERE t1.b IN (SELECT (t1.a + t1.b)/2 FROM prt1_e t1 WHERE t1.a %25 = 0)) AND t1.a % 25 = 0 ORDER BY t1.a; +SELECT t1.* FROM prt1 t1 WHERE t1.a IN (SELECT t1.b FROM prt2 t1 WHERE t1.b IN (SELECT (t1.a + t1.b)/2 FROM prt1_e t1 WHERE t1.a %25 = 0)) AND t1.a % 25 = 0 ORDER BY t1.a; +SELECT t1.* FROM uprt1 t1 WHERE t1.a IN (SELECT t1.b FROM uprt2 t1 WHERE t1.b IN (SELECT (t1.a + t1.b)/2 FROM uprt1_e t1 WHERE t1.a %25 = 0)) AND t1.a % 25 = 0 ORDER BY t1.a; + +EXPLAIN (VERBOSE, COSTS OFF) +SELECT t1.a, t1.c, t2.b, t2.c, t3.a + t3.b, t3.c FROM (prt1 t1 LEFT JOIN prt2 t2 ON t1.a = t2.b) RIGHT JOIN prt1_e t3 ON (t1.a = (t3.a + t3.b)/2) WHERE t3.a % 25 = 0 ORDER BY t1.a, t2.b, t3.a + t3.b; +SELECT t1.a, t1.c, t2.b, t2.c, t3.a + t3.b, t3.c FROM (prt1 t1 LEFT JOIN prt2 t2 ON t1.a = t2.b) RIGHT JOIN prt1_e t3 ON (t1.a = (t3.a + t3.b)/2) WHERE t3.a % 25 = 0 ORDER BY t1.a, t2.b, t3.a + t3.b; +SELECT t1.a, t1.c, t2.b, t2.c, t3.a + t3.b, t3.c FROM (uprt1 t1 LEFT JOIN uprt2 t2 ON t1.a = t2.b) RIGHT JOIN uprt1_e t3 ON (t1.a = (t3.a + t3.b)/2) WHERE t3.a % 25 = 0 ORDER BY t1.a, t2.b, t3.a + t3.b; + +SET enable_seqscan TO off; + +EXPLAIN (VERBOSE, COSTS OFF) +SELECT t1.a, t1.c, t2.b, t2.c, t3.a + t3.b, t3.c FROM (prt1 t1 RIGHT JOIN prt2 t2 ON t1.a = t2.b) RIGHT JOIN prt1_e t3 ON (t2.b = (t3.a + t3.b)/2) WHERE t3.a % 25 = 0 ORDER BY t1.a, t2.b, t3.a + t3.b; +SELECT t1.a, t1.c, t2.b, t2.c, t3.a + t3.b, t3.c FROM (prt1 t1 RIGHT JOIN prt2 t2 ON t1.a = t2.b) RIGHT JOIN prt1_e t3 ON (t2.b = (t3.a + t3.b)/2) WHERE t3.a % 25 = 0 ORDER BY t1.a, t2.b, t3.a + t3.b; +SELECT t1.a, t1.c, t2.b, t2.c, t3.a + t3.b, t3.c FROM (uprt1 t1 RIGHT JOIN uprt2 t2 ON t1.a = t2.b) RIGHT JOIN uprt1_e t3 ON (t2.b = (t3.a + t3.b)/2) WHERE t3.a % 25 = 0 ORDER BY t1.a, t2.b, t3.a + t3.b; + +EXPLAIN (VERBOSE, COSTS OFF) +SELECT t1.* FROM prt1 t1 WHERE t1.a IN (SELECT t1.b FROM prt2 t1 WHERE t1.b IN (SELECT (t1.a + t1.b)/2 FROM prt1_e t1 WHERE t1.a %25 = 0)) AND t1.a % 25 = 0 ORDER BY t1.a; +SELECT t1.* FROM prt1 t1 WHERE t1.a IN (SELECT t1.b FROM prt2 t1 WHERE t1.b IN (SELECT (t1.a + t1.b)/2 FROM prt1_e t1 WHERE t1.a %25 = 0)) AND t1.a % 25 = 0 ORDER BY t1.a; +SELECT t1.* FROM uprt1 t1 WHERE t1.a IN (SELECT t1.b FROM uprt2 t1 WHERE t1.b IN (SELECT (t1.a + t1.b)/2 FROM uprt1_e t1 WHERE t1.a %25 = 0)) AND t1.a % 25 = 0 ORDER BY t1.a; + +EXPLAIN (VERBOSE, COSTS OFF) +SELECT t1.a, t1.c, t2.b, t2.c, t3.a + t3.b, t3.c FROM (prt1 t1 LEFT JOIN prt2 t2 ON t1.a = t2.b) RIGHT JOIN prt1_e t3 ON (t1.a = (t3.a + t3.b)/2) WHERE t3.a % 25 = 0 ORDER BY t1.a, t2.b, t3.a + t3.b; +SELECT t1.a, t1.c, t2.b, t2.c, t3.a + t3.b, t3.c FROM (prt1 t1 LEFT JOIN prt2 t2 ON t1.a = t2.b) RIGHT JOIN prt1_e t3 ON (t1.a = (t3.a + t3.b)/2) WHERE t3.a % 25 = 0 ORDER BY t1.a, t2.b, t3.a + t3.b; +SELECT t1.a, t1.c, t2.b, t2.c, t3.a + t3.b, t3.c FROM (uprt1 t1 LEFT JOIN uprt2 t2 ON t1.a = t2.b) RIGHT JOIN uprt1_e t3 ON (t1.a = (t3.a + t3.b)/2) WHERE t3.a % 25 = 0 ORDER BY t1.a, t2.b, t3.a + t3.b; + +-- lateral references and parameterized paths +EXPLAIN (VERBOSE, COSTS OFF) +SELECT * FROM prt1 t1 LEFT JOIN LATERAL + (SELECT t2.a AS t2a, t3.a AS t3a, least(t1.a,t2.a,t3.a) FROM prt1 t2 JOIN prt2 t3 ON (t2.a = t3.b)) ss + ON t1.a = ss.t2a WHERE t1.a % 25 = 0 ORDER BY t1.a; +SELECT * FROM prt1 t1 LEFT JOIN LATERAL + (SELECT t2.a AS t2a, t3.a AS t3a, least(t1.a,t2.a,t3.a) FROM prt1 t2 JOIN prt2 t3 ON (t2.a = t3.b)) ss + ON t1.a = ss.t2a WHERE t1.a % 25 = 0 ORDER BY t1.a; +SELECT * FROM uprt1 t1 LEFT JOIN LATERAL + (SELECT t2.a AS t2a, t3.a AS t3a, least(t1.a,t2.a,t3.a) FROM uprt1 t2 JOIN uprt2 t3 ON (t2.a = t3.b)) ss + ON t1.a = ss.t2a WHERE t1.a % 25 = 0 ORDER BY t1.a; + +EXPLAIN (VERBOSE, COSTS OFF) +SELECT * FROM prt1 t1 LEFT JOIN LATERAL + (SELECT t2.a AS t2a, t3.a AS t3a, least(t1.a,t2.a,t3.a) FROM prt1 t2 JOIN prt2 t3 ON (t2.a = t3.b)) ss + ON t1.b = ss.t2a WHERE t1.a % 25 = 0 ORDER BY t1.a; +SELECT * FROM prt1 t1 LEFT JOIN LATERAL + (SELECT t2.a AS t2a, t3.a AS t3a, least(t1.a,t2.a,t3.a) FROM prt1 t2 JOIN prt2 t3 ON (t2.a = t3.b)) ss + ON t1.b = ss.t2a WHERE t1.a % 25 = 0 ORDER BY t1.a; +SELECT * FROM uprt1 t1 LEFT JOIN LATERAL + (SELECT t2.a AS t2a, t3.a AS t3a, least(t1.a,t2.a,t3.a) FROM uprt1 t2 JOIN uprt2 t3 ON (t2.a = t3.b)) ss + ON t1.b = ss.t2a WHERE t1.a % 25 = 0 ORDER BY t1.a; + +RESET enable_hashjoin; +RESET enable_nestloop; +RESET enable_seqscan; + +-- +-- partitioned by multiple columns +-- +CREATE TABLE prt1_m (a int, b int, c varchar) PARTITION BY RANGE(a, ((a + b)/2)); +CREATE TABLE prt1_m_p1 PARTITION OF prt1_m FOR VALUES FROM (0, 0) TO (250, 250); +CREATE TABLE prt1_m_p2 PARTITION OF prt1_m FOR VALUES FROM (250, 250) TO (500, 500); +CREATE TABLE prt1_m_p3 PARTITION OF prt1_m FOR VALUES FROM (500, 500) TO (600, 600); +INSERT INTO prt1_m SELECT i, i, to_char(i, 'FM0000') FROM generate_series(0, 599, 2) i; +ANALYZE prt1_m; +ANALYZE prt1_m_p1; +ANALYZE prt1_m_p2; +ANALYZE prt1_m_p3; +-- TODO: This table is created only for testing the results. Remove once +-- results are tested. +CREATE TABLE uprt1_m AS SELECT * FROM prt1_m; + +CREATE TABLE prt2_m (a int, b int, c varchar) PARTITION BY RANGE(((b + a)/2), b); +CREATE TABLE prt2_m_p1 PARTITION OF prt2_m FOR VALUES FROM (0, 0) TO (250, 250); +CREATE TABLE prt2_m_p2 PARTITION OF prt2_m FOR VALUES FROM (250, 250) TO (500, 500); +CREATE TABLE prt2_m_p3 PARTITION OF prt2_m FOR VALUES FROM (500, 500) TO (600, 600); +INSERT INTO prt2_m SELECT i, i, to_char(i, 'FM0000') FROM generate_series(0, 599, 3) i; +ANALYZE prt2_m; +ANALYZE prt2_m_p1; +ANALYZE prt2_m_p2; +ANALYZE prt2_m_p3; +-- TODO: This table is created only for testing the results. Remove once +-- results are tested. +CREATE TABLE uprt2_m AS SELECT * FROM prt2_m; + +EXPLAIN (VERBOSE, COSTS OFF) +SELECT t1.a, t1.c, t2.b, t2.c FROM prt1_m t1 RIGHT JOIN prt2_m t2 ON t1.a = (t2.b + t2.a)/2 AND t2.b = (t1.a + t1.b)/2 WHERE t2.b % 25 = 0 ORDER BY t1.a, t2.b; +SELECT t1.a, t1.c, t2.b, t2.c FROM prt1_m t1 RIGHT JOIN prt2_m t2 ON t1.a = (t2.b + t2.a)/2 AND t2.b = (t1.a + t1.b)/2 WHERE t2.b % 25 = 0 ORDER BY t1.a, t2.b; +SELECT t1.a, t1.c, t2.b, t2.c FROM uprt1_m t1 RIGHT JOIN uprt2_m t2 ON t1.a = (t2.b + t2.a)/2 AND t2.b = (t1.a + t1.b)/2 WHERE t2.b % 25 = 0 ORDER BY t1.a, t2.b; + +EXPLAIN (VERBOSE, COSTS OFF) +SELECT t1.a, t1.c, t2.b, t2.c FROM (SELECT * FROM prt1_m WHERE prt1_m.a % 25 = 0) t1 FULL JOIN (SELECT * FROM prt2_m WHERE prt2_m.b % 25 = 0) t2 ON (t1.a = (t2.b + t2.a)/2 AND t2.b = (t1.a + t1.b)/2) ORDER BY t1.a, t2.b; +SELECT t1.a, t1.c, t2.b, t2.c FROM (SELECT * FROM prt1_m WHERE prt1_m.a % 25 = 0) t1 FULL JOIN (SELECT * FROM prt2_m WHERE prt2_m.b % 25 = 0) t2 ON (t1.a = (t2.b + t2.a)/2 AND t2.b = (t1.a + t1.b)/2) ORDER BY t1.a, t2.b; +SELECT t1.a, t1.c, t2.b, t2.c FROM (SELECT * FROM uprt1_m t1 WHERE t1.a % 25 = 0) t1 FULL JOIN (SELECT * FROM uprt2_m t2 WHERE t2.b % 25 = 0) t2 ON (t1.a = (t2.b + t2.a)/2 AND t2.b = (t1.a + t1.b)/2) ORDER BY t1.a, t2.b; + +-- +-- tests for list partitioned tables. +-- +CREATE TABLE plt1 (a int, b int, c text) PARTITION BY LIST(c); +CREATE TABLE plt1_p1 PARTITION OF plt1 FOR VALUES IN ('0000', '0003', '0004', '0010'); +CREATE TABLE plt1_p2 PARTITION OF plt1 FOR VALUES IN ('0001', '0005', '0002', '0009'); +CREATE TABLE plt1_p3 PARTITION OF plt1 FOR VALUES IN ('0006', '0007', '0008', '0011'); +INSERT INTO plt1 SELECT i, i, to_char(i/50, 'FM0000') FROM generate_series(0, 599, 2) i; +ANALYZE plt1; +ANALYZE plt1_p1; +ANALYZE plt1_p2; +ANALYZE plt1_p3; +-- TODO: This table is created only for testing the results. Remove once +-- results are tested. +CREATE TABLE uplt1 AS SELECT * FROM plt1; + +CREATE TABLE plt2 (a int, b int, c text) PARTITION BY LIST(c); +CREATE TABLE plt2_p1 PARTITION OF plt2 FOR VALUES IN ('0000', '0003', '0004', '0010'); +CREATE TABLE plt2_p2 PARTITION OF plt2 FOR VALUES IN ('0001', '0005', '0002', '0009'); +CREATE TABLE plt2_p3 PARTITION OF plt2 FOR VALUES IN ('0006', '0007', '0008', '0011'); +INSERT INTO plt2 SELECT i, i, to_char(i/50, 'FM0000') FROM generate_series(0, 599, 3) i; +ANALYZE plt2; +ANALYZE plt2_p1; +ANALYZE plt2_p2; +ANALYZE plt2_p3; +-- TODO: This table is created only for testing the results. Remove once +-- results are tested. +CREATE TABLE uplt2 AS SELECT * FROM plt2; + +-- +-- list partitioned by expression +-- +CREATE TABLE plt1_e (a int, b int, c text) PARTITION BY LIST(ltrim(c, 'A')); +CREATE TABLE plt1_e_p1 PARTITION OF plt1_e FOR VALUES IN ('0000', '0003', '0004', '0010'); +CREATE TABLE plt1_e_p2 PARTITION OF plt1_e FOR VALUES IN ('0001', '0005', '0002', '0009'); +CREATE TABLE plt1_e_p3 PARTITION OF plt1_e FOR VALUES IN ('0006', '0007', '0008', '0011'); +INSERT INTO plt1_e SELECT i, i, 'A' || to_char(i/50, 'FM0000') FROM generate_series(0, 599, 2) i; +ANALYZE plt1_e; +ANALYZE plt1_e_p1; +ANALYZE plt1_e_p2; +ANALYZE plt1_e_p3; +-- TODO: This table is created only for testing the results. Remove once +-- results are tested. +CREATE TABLE uplt1_e AS SELECT * FROM plt1_e; + +-- +-- N-way join +-- +EXPLAIN (VERBOSE, COSTS OFF) +SELECT avg(t1.a), avg(t2.b), avg(t3.a + t3.b), t1.c, t2.c, t3.c FROM plt1 t1, plt2 t2, plt1_e t3 WHERE t1.c = t2.c AND ltrim(t3.c, 'A') = t1.c GROUP BY t1.c, t2.c, t3.c ORDER BY t1.c, t2.c, t3.c; +SELECT avg(t1.a), avg(t2.b), avg(t3.a + t3.b), t1.c, t2.c, t3.c FROM plt1 t1, plt2 t2, plt1_e t3 WHERE t1.c = t2.c AND ltrim(t3.c, 'A') = t1.c GROUP BY t1.c, t2.c, t3.c ORDER BY t1.c, t2.c, t3.c; +SELECT avg(t1.a), avg(t2.b), avg(t3.a + t3.b), t1.c, t2.c, t3.c FROM uplt1 t1, uplt2 t2, uplt1_e t3 WHERE t1.c = t2.c AND ltrim(t3.c, 'A') = t1.c GROUP BY t1.c, t2.c, t3.c ORDER BY t1.c, t2.c, t3.c; + +EXPLAIN (VERBOSE, COSTS OFF) +SELECT t1.a, t1.c, t2.b, t2.c, t3.a + t3.b, t3.c FROM (plt1 t1 LEFT JOIN plt2 t2 ON t1.a = t2.b AND t1.c = t2.c) LEFT JOIN plt1_e t3 ON (t1.a = t3.a AND ltrim(t3.c, 'A') = t1.c) WHERE t1.a % 25 = 0 ORDER BY t1.a, t2.b, t3.a + t3.b; +SELECT t1.a, t1.c, t2.b, t2.c, t3.a + t3.b, t3.c FROM (plt1 t1 LEFT JOIN plt2 t2 ON t1.a = t2.b AND t1.c = t2.c) LEFT JOIN plt1_e t3 ON (t1.a = t3.a AND ltrim(t3.c, 'A') = t1.c) WHERE t1.a % 25 = 0 ORDER BY t1.a, t2.b, t3.a + t3.b; +SELECT t1.a, t1.c, t2.b, t2.c, t3.a + t3.b, t3.c FROM (uplt1 t1 LEFT JOIN uplt2 t2 ON t1.a = t2.b AND t1.c = t2.c) LEFT JOIN uplt1_e t3 ON (t1.a = t3.a AND ltrim(t3.c, 'A') = t1.c) WHERE t1.a % 25 = 0 ORDER BY t1.a, t2.b, t3.a + t3.b; + +EXPLAIN (VERBOSE, COSTS OFF) +SELECT t1.a, t1.c, t2.b, t2.c, t3.a + t3.b, t3.c FROM (plt1 t1 LEFT JOIN plt2 t2 ON t1.a = t2.b AND t1.c = t2.c) LEFT JOIN plt1_e t3 ON (t2.b = t3.a AND t2.c = ltrim(t3.c, 'A')) WHERE t1.a % 25 = 0 ORDER BY t1.a, t2.b, t3.a + t3.b; +SELECT t1.a, t1.c, t2.b, t2.c, t3.a + t3.b, t3.c FROM (plt1 t1 LEFT JOIN plt2 t2 ON t1.a = t2.b AND t1.c = t2.c) LEFT JOIN plt1_e t3 ON (t2.b = t3.a AND t2.c = ltrim(t3.c, 'A')) WHERE t1.a % 25 = 0 ORDER BY t1.a, t2.b, t3.a + t3.b; +SELECT t1.a, t1.c, t2.b, t2.c, t3.a + t3.b, t3.c FROM (uplt1 t1 LEFT JOIN uplt2 t2 ON t1.a = t2.b AND t1.c = t2.c) LEFT JOIN uplt1_e t3 ON (t2.b = t3.a AND t2.c = ltrim(t3.c, 'A')) WHERE t1.a % 25 = 0 ORDER BY t1.a, t2.b, t3.a + t3.b; + +EXPLAIN (VERBOSE, COSTS OFF) +SELECT t1.a, t1.c, t2.b, t2.c, t3.a + t3.b, t3.c FROM (plt1 t1 LEFT JOIN plt2 t2 ON t1.a = t2.b AND t1.c = t2.c) RIGHT JOIN plt1_e t3 ON (t1.a = t3.a AND ltrim(t3.c, 'A') = t1.c) WHERE t3.a % 25 = 0 ORDER BY t1.a, t2.b, t3.a + t3.b; +SELECT t1.a, t1.c, t2.b, t2.c, t3.a + t3.b, t3.c FROM (plt1 t1 LEFT JOIN plt2 t2 ON t1.a = t2.b AND t1.c = t2.c) RIGHT JOIN plt1_e t3 ON (t1.a = t3.a AND ltrim(t3.c, 'A') = t1.c) WHERE t3.a % 25 = 0 ORDER BY t1.a, t2.b, t3.a + t3.b; +SELECT t1.a, t1.c, t2.b, t2.c, t3.a + t3.b, t3.c FROM (uplt1 t1 LEFT JOIN uplt2 t2 ON t1.a = t2.b AND t1.c = t2.c) RIGHT JOIN uplt1_e t3 ON (t1.a = t3.a AND ltrim(t3.c, 'A') = t1.c) WHERE t3.a % 25 = 0 ORDER BY t1.a, t2.b, t3.a + t3.b; + +EXPLAIN (VERBOSE, COSTS OFF) +SELECT t1.a, t1.c, t2.b, t2.c, t3.a + t3.b, t3.c FROM (plt1 t1 RIGHT JOIN plt2 t2 ON t1.a = t2.b AND t1.c = t2.c) RIGHT JOIN plt1_e t3 ON (t2.b = t3.a AND t2.c = ltrim(t3.c, 'A')) WHERE t3.a % 25 = 0 ORDER BY t1.a, t2.b, t3.a + t3.b; +SELECT t1.a, t1.c, t2.b, t2.c, t3.a + t3.b, t3.c FROM (plt1 t1 RIGHT JOIN plt2 t2 ON t1.a = t2.b AND t1.c = t2.c) RIGHT JOIN plt1_e t3 ON (t2.b = t3.a AND t2.c = ltrim(t3.c, 'A')) WHERE t3.a % 25 = 0 ORDER BY t1.a, t2.b, t3.a + t3.b; +SELECT t1.a, t1.c, t2.b, t2.c, t3.a + t3.b, t3.c FROM (uplt1 t1 RIGHT JOIN uplt2 t2 ON t1.a = t2.b AND t1.c = t2.c) RIGHT JOIN uplt1_e t3 ON (t2.b = t3.a AND t2.c = ltrim(t3.c, 'A')) WHERE t3.a % 25 = 0 ORDER BY t1.a, t2.b, t3.a + t3.b; + +EXPLAIN (VERBOSE, COSTS OFF) +SELECT t1.a, t1.c, t2.b, t2.c, t3.a + t3.b, t3.c FROM ((SELECT * FROM plt1 WHERE plt1.a % 25 = 0) t1 FULL JOIN (SELECT * FROM plt2 WHERE plt2.b % 25 = 0) t2 ON (t1.a = t2.b AND t1.c = t2.c)) FULL JOIN (SELECT * FROM plt1_e WHERE plt1_e.a % 25 = 0) t3 ON (t1.a = t3.a AND ltrim(t3.c, 'A') = t1.c) ORDER BY t1.a, t2.b, t3.a + t3.b; +SELECT t1.a, t1.c, t2.b, t2.c, t3.a + t3.b, t3.c FROM ((SELECT * FROM plt1 WHERE plt1.a % 25 = 0) t1 FULL JOIN (SELECT * FROM plt2 WHERE plt2.b % 25 = 0) t2 ON (t1.a = t2.b AND t1.c = t2.c)) FULL JOIN (SELECT * FROM plt1_e WHERE plt1_e.a % 25 = 0) t3 ON (t1.a = t3.a AND ltrim(t3.c, 'A') = t1.c) ORDER BY t1.a, t2.b, t3.a + t3.b; +SELECT t1.a, t1.c, t2.b, t2.c, t3.a + t3.b, t3.c FROM ((SELECT * FROM uplt1 WHERE uplt1.a % 25 = 0) t1 FULL JOIN (SELECT * FROM uplt2 WHERE uplt2.b % 25 = 0) t2 ON (t1.a = t2.b AND t1.c = t2.c)) FULL JOIN (SELECT * FROM uplt1_e WHERE uplt1_e.a % 25 = 0) t3 ON (t1.a = t3.a AND ltrim(t3.c, 'A') = t1.c) ORDER BY t1.a, t2.b, t3.a + t3.b; + +-- Semi-join +EXPLAIN (VERBOSE, COSTS OFF) +SELECT t1.* FROM plt1 t1 WHERE t1.c IN (SELECT t1.c FROM plt2 t1, plt1_e t2 WHERE t1.c = ltrim(t2.c, 'A')) AND t1.a % 25 = 0 ORDER BY t1.a; +SELECT t1.* FROM plt1 t1 WHERE t1.c IN (SELECT t1.c FROM plt2 t1, plt1_e t2 WHERE t1.c = ltrim(t2.c, 'A')) AND t1.a % 25 = 0 ORDER BY t1.a; +SELECT t1.* FROM uplt1 t1 WHERE t1.c IN (SELECT t1.c FROM uplt2 t1, uplt1_e t2 WHERE t1.c = ltrim(t2.c, 'A')) AND t1.a % 25 = 0 ORDER BY t1.a; + +EXPLAIN (VERBOSE, COSTS OFF) +SELECT t1.* FROM plt1 t1 WHERE t1.c IN (SELECT t1.c FROM plt2 t1 WHERE t1.c IN (SELECT ltrim(t1.c, 'A') FROM plt1_e t1 WHERE t1.a % 25 = 0)) AND t1.a % 25 = 0 ORDER BY t1.a; +SELECT t1.* FROM plt1 t1 WHERE t1.c IN (SELECT t1.c FROM plt2 t1 WHERE t1.c IN (SELECT ltrim(t1.c, 'A') FROM plt1_e t1 WHERE t1.a % 25 = 0)) AND t1.a % 25 = 0 ORDER BY t1.a; +SELECT t1.* FROM uplt1 t1 WHERE t1.c IN (SELECT t1.c FROM uplt2 t1 WHERE t1.c IN (SELECT ltrim(t1.c, 'A') FROM uplt1_e t1 WHERE t1.a % 25 = 0)) AND t1.a % 25 = 0 ORDER BY t1.a; + +-- +-- negative testcases +-- + +-- joins where one of the relations is proven empty +EXPLAIN (VERBOSE, COSTS OFF) +SELECT t1.a, t1.c, t2.b, t2.c FROM prt1 t1, prt2 t2 WHERE t1.a = t2.b AND t1.a = 1 AND t1.a = 2; + +EXPLAIN (VERBOSE, COSTS OFF) +SELECT t1.a, t1.c, t2.b, t2.c FROM (SELECT * FROM prt1 WHERE a = 1 AND a = 2) t1 LEFT JOIN prt2 t2 ON t1.a = t2.b; + +EXPLAIN (VERBOSE, COSTS OFF) +SELECT t1.a, t1.c, t2.b, t2.c FROM (SELECT * FROM prt1 WHERE a = 1 AND a = 2) t1 RIGHT JOIN prt2 t2 ON t1.a = t2.b WHERE t2.a % 25 = 0 ORDER BY t1.a, t2.b; + +EXPLAIN (VERBOSE, COSTS OFF) +SELECT t1.a, t1.c, t2.b, t2.c FROM (SELECT * FROM prt1 WHERE a = 1 AND a = 2) t1 FULL JOIN prt2 t2 ON t1.a = t2.b WHERE t2.a % 25 = 0 ORDER BY t1.a, t2.b; + +CREATE TABLE prt1_n (a int, b int, c varchar) PARTITION BY RANGE(c); +CREATE TABLE prt1_n_p1 PARTITION OF prt1_n FOR VALUES FROM ('0000') TO ('0250'); +CREATE TABLE prt1_n_p2 PARTITION OF prt1_n FOR VALUES FROM ('0250') TO ('0500'); +INSERT INTO prt1_n SELECT i, i, to_char(i, 'FM0000') FROM generate_series(0, 499, 2) i; +ANALYZE prt1_n; +ANALYZE prt1_n_p1; +ANALYZE prt1_n_p2; + +CREATE TABLE prt2_n (a int, b int, c text) PARTITION BY LIST(c); +CREATE TABLE prt2_n_p1 PARTITION OF prt2_n FOR VALUES IN ('0000', '0003', '0004', '0010', '0006', '0007'); +CREATE TABLE prt2_n_p2 PARTITION OF prt2_n FOR VALUES IN ('0001', '0005', '0002', '0009', '0008', '0011'); +INSERT INTO prt2_n SELECT i, i, to_char(i/50, 'FM0000') FROM generate_series(0, 599, 2) i; +ANALYZE prt2_n; +ANALYZE prt2_n_p1; +ANALYZE prt2_n_p2; + +CREATE TABLE prt3_n (a int, b int, c text) PARTITION BY LIST(c); +CREATE TABLE prt3_n_p1 PARTITION OF prt3_n FOR VALUES IN ('0000', '0004', '0006', '0007'); +CREATE TABLE prt3_n_p2 PARTITION OF prt3_n FOR VALUES IN ('0001', '0002', '0008', '0010'); +CREATE TABLE prt3_n_p3 PARTITION OF prt3_n FOR VALUES IN ('0003', '0005', '0009', '0011'); +INSERT INTO prt2_n SELECT i, i, to_char(i/50, 'FM0000') FROM generate_series(0, 599, 2) i; +ANALYZE prt3_n; +ANALYZE prt3_n_p1; +ANALYZE prt3_n_p2; +ANALYZE prt3_n_p3; + +CREATE TABLE prt4_n (a int, b int, c text) PARTITION BY RANGE(a); +CREATE TABLE prt4_n_p1 PARTITION OF prt4_n FOR VALUES FROM (0) TO (300); +CREATE TABLE prt4_n_p2 PARTITION OF prt4_n FOR VALUES FROM (300) TO (500); +CREATE TABLE prt4_n_p3 PARTITION OF prt4_n FOR VALUES FROM (500) TO (600); +INSERT INTO prt4_n SELECT i, i, to_char(i, 'FM0000') FROM generate_series(0, 599, 2) i; +ANALYZE prt4_n; +ANALYZE prt4_n_p1; +ANALYZE prt4_n_p2; +ANALYZE prt4_n_p3; + +-- partition-wise join can not be applied if the partition ranges differ +EXPLAIN (COSTS OFF) +SELECT t1.a, t1.c, t2.b, t2.c FROM prt1 t1, prt4_n t2 WHERE t1.a = t2.a; +EXPLAIN (COSTS OFF) +SELECT t1.a, t1.c, t2.b, t2.c FROM prt1 t1 FULL JOIN prt4_n t2 ON t1.a = t2.a; + +-- partition-wise join can not be applied if there are no equi-join conditions +-- between partition keys +EXPLAIN (COSTS OFF) +SELECT t1.a, t1.c, t2.b, t2.c FROM prt1 t1 LEFT JOIN prt2 t2 ON (t1.a < t2.b); + +-- equi-join with join condition on partial keys does not qualify for +-- partition-wise join +EXPLAIN (COSTS OFF) +SELECT t1.a, t1.c, t2.b, t2.c FROM prt1_m t1, prt2_m t2 WHERE t1.a = (t2.b + t2.a)/2 AND t1.a % 25 = 0; + +-- equi-join between out-of-order partition key columns does not qualify for +-- partition-wise join +EXPLAIN (COSTS OFF) +SELECT t1.a, t1.c, t2.b, t2.c FROM prt1_m t1 LEFT JOIN prt2_m t2 ON t1.a = t2.b WHERE t1.a % 25 = 0; + +-- equi-join between non-key columns does not qualify for partition-wise join +EXPLAIN (COSTS OFF) +SELECT t1.a, t1.c, t2.b, t2.c FROM prt1_m t1 LEFT JOIN prt2_m t2 ON t1.c = t2.c WHERE t1.a % 25 = 0; + +-- partition-wise join can not be applied for a join between list and range +-- partitioned table +EXPLAIN (COSTS OFF) +SELECT t1.a, t1.c, t2.b, t2.c FROM prt1_n t1, prt2_n t2 WHERE t1.c = t2.c; +EXPLAIN (COSTS OFF) +SELECT t1.a, t1.c, t2.b, t2.c FROM prt1_n t1 LEFT JOIN prt2_n t2 ON (t1.c = t2.c); + +-- partition-wise join can not be applied between tables with different +-- partition lists +EXPLAIN (COSTS OFF) +SELECT t1.a, t1.c, t2.b, t2.c FROM prt1_n t1 RIGHT JOIN prt1 t2 ON (t1.c = t2.c); +EXPLAIN (COSTS OFF) +SELECT t1.a, t1.c, t2.b, t2.c FROM prt1_n t1 FULL JOIN prt1 t2 ON (t1.c = t2.c); -- 1.7.9.5