| -- |
| -- UNION (also INTERSECT, EXCEPT) |
| -- |
| |
| -- Simple UNION constructs |
| |
| SELECT 1 AS two UNION SELECT 2; |
| |
| SELECT 1 AS one UNION SELECT 1; |
| |
| SELECT 1 AS two UNION ALL SELECT 2; |
| |
| SELECT 1 AS two UNION ALL SELECT 1; |
| |
| SELECT 1 AS three UNION SELECT 2 UNION SELECT 3; |
| |
| SELECT 1 AS two UNION SELECT 2 UNION SELECT 2; |
| |
| SELECT 1 AS three UNION SELECT 2 UNION ALL SELECT 2; |
| |
| SELECT 1.1 AS two UNION SELECT 2.2; |
| |
| -- Mixed types |
| |
| SELECT 1.1 AS two UNION SELECT 2; |
| |
| SELECT 1 AS two UNION SELECT 2.2; |
| |
| SELECT 1 AS one UNION SELECT 1.0::float8; |
| |
| SELECT 1.1 AS two UNION ALL SELECT 2; |
| |
| SELECT 1.0::float8 AS two UNION ALL SELECT 1; |
| |
| SELECT 1.1 AS three UNION SELECT 2 UNION SELECT 3; |
| |
| SELECT 1.1::float8 AS two UNION SELECT 2 UNION SELECT 2.0::float8; |
| |
| SELECT 1.1 AS three UNION SELECT 2 UNION ALL SELECT 2; |
| |
| SELECT 1.1 AS two UNION (SELECT 2 UNION ALL SELECT 2); |
| |
| -- |
| -- Try testing from tables... |
| -- |
| |
| SELECT f1 AS five FROM FLOAT8_TBL |
| UNION |
| SELECT f1 FROM FLOAT8_TBL ORDER BY 1; |
| |
| SELECT f1 AS ten FROM FLOAT8_TBL |
| UNION ALL |
| SELECT f1 FROM FLOAT8_TBL ORDER BY 1; |
| |
| SELECT f1 AS nine FROM FLOAT8_TBL |
| UNION |
| SELECT f1 FROM INT4_TBL ORDER BY 1; |
| |
| SELECT f1 AS ten FROM FLOAT8_TBL |
| UNION ALL |
| SELECT f1 FROM INT4_TBL ORDER BY 1; |
| |
| SELECT f1 AS five FROM FLOAT8_TBL |
| WHERE f1 BETWEEN -1e6 AND 1e6 |
| UNION |
| SELECT f1 FROM INT4_TBL |
| WHERE f1 BETWEEN 0 AND 1000000 ORDER BY 1; |
| |
| SELECT CAST(f1 AS char(4)) AS three FROM VARCHAR_TBL |
| UNION |
| SELECT f1 FROM CHAR_TBL ORDER BY 1; |
| |
| SELECT f1 AS three FROM VARCHAR_TBL |
| UNION |
| SELECT CAST(f1 AS varchar) FROM CHAR_TBL ORDER BY 1; |
| |
| SELECT f1 AS eight FROM VARCHAR_TBL |
| UNION ALL |
| SELECT f1 FROM CHAR_TBL ORDER BY 1; |
| |
| SELECT f1 AS five FROM TEXT_TBL |
| UNION |
| SELECT f1 FROM VARCHAR_TBL |
| UNION |
| SELECT TRIM(TRAILING FROM f1) FROM CHAR_TBL ORDER BY 1; |
| |
| -- |
| -- INTERSECT and EXCEPT |
| -- |
| |
| SELECT q2 FROM int8_tbl INTERSECT SELECT q1 FROM int8_tbl ORDER BY 1; |
| |
| SELECT q2 FROM int8_tbl INTERSECT ALL SELECT q1 FROM int8_tbl ORDER BY 1; |
| |
| SELECT q2 FROM int8_tbl EXCEPT SELECT q1 FROM int8_tbl ORDER BY 1; |
| |
| SELECT q2 FROM int8_tbl EXCEPT ALL SELECT q1 FROM int8_tbl ORDER BY 1; |
| |
| SELECT q2 FROM int8_tbl EXCEPT ALL SELECT DISTINCT q1 FROM int8_tbl ORDER BY 1; |
| |
| SELECT q1 FROM int8_tbl EXCEPT SELECT q2 FROM int8_tbl ORDER BY 1; |
| |
| SELECT q1 FROM int8_tbl EXCEPT ALL SELECT q2 FROM int8_tbl ORDER BY 1; |
| |
| SELECT q1 FROM int8_tbl EXCEPT ALL SELECT DISTINCT q2 FROM int8_tbl ORDER BY 1; |
| |
| -- |
| -- Mixed types |
| -- |
| |
| SELECT f1 FROM float8_tbl INTERSECT SELECT f1 FROM int4_tbl ORDER BY 1; |
| |
| SELECT f1 FROM float8_tbl EXCEPT SELECT f1 FROM int4_tbl ORDER BY 1; |
| |
| -- |
| -- Operator precedence and (((((extra))))) parentheses |
| -- |
| |
| SELECT q1 FROM int8_tbl INTERSECT SELECT q2 FROM int8_tbl UNION ALL SELECT q2 FROM int8_tbl ORDER BY 1; |
| |
| SELECT q1 FROM int8_tbl INTERSECT (((SELECT q2 FROM int8_tbl UNION ALL SELECT q2 FROM int8_tbl))) ORDER BY 1; |
| |
| (((SELECT q1 FROM int8_tbl INTERSECT SELECT q2 FROM int8_tbl))) UNION ALL SELECT q2 FROM int8_tbl ORDER BY 1; |
| |
| SELECT q1 FROM int8_tbl UNION ALL SELECT q2 FROM int8_tbl EXCEPT SELECT q1 FROM int8_tbl ORDER BY 1; |
| |
| SELECT q1 FROM int8_tbl UNION ALL (((SELECT q2 FROM int8_tbl EXCEPT SELECT q1 FROM int8_tbl))) ORDER BY 1; |
| |
| (((SELECT q1 FROM int8_tbl UNION ALL SELECT q2 FROM int8_tbl))) EXCEPT SELECT q1 FROM int8_tbl ORDER BY 1; |
| |
| -- |
| -- Subqueries with ORDER BY & LIMIT clauses |
| -- |
| |
| -- In this syntax, ORDER BY/LIMIT apply to the result of the EXCEPT |
| SELECT q1,q2 FROM int8_tbl EXCEPT SELECT q2,q1 FROM int8_tbl |
| ORDER BY q2,q1; |
| |
| -- This should fail, because q2 isn't a name of an EXCEPT output column |
| SELECT q1 FROM int8_tbl EXCEPT SELECT q2 FROM int8_tbl ORDER BY q2 LIMIT 1; |
| |
| -- But this should work: |
| SELECT q1 FROM int8_tbl EXCEPT (((SELECT q2 FROM int8_tbl ORDER BY q2 LIMIT 1))) ORDER BY 1; |
| |
| -- |
| -- New syntaxes (7.1) permit new tests |
| -- |
| |
| (((((select * from int8_tbl))))) ORDER BY 1,2; |
| |
| create temp table t_union1 (a int, b int); |
| select distinct a, null as c from t_union1 union select a, b from t_union1; |
| drop table t_union1; |
| |
| select null union select distinct null; |
| |
| select 1 union select distinct null; |
| |
| select 1 a, NULL b, NULL c UNION SELECT 2, 3, NULL UNION SELECT 3, NULL, 4; |
| |
| select ARRAY[1, 2, 3] union select distinct null; |
| |
| -- This can preserve domain types, but we keep compatibility for now |
| -- See MPP-7509 |
| select pg_typeof(a) from (select 'a'::information_schema.sql_identifier a union all |
| select 'b'::information_schema.sql_identifier)a; |
| |
| (select * from ( |
| (select '1' as a union select null) |
| union |
| (select 1 union select distinct null) |
| )s) |
| union |
| (select * from ( |
| (select '1' union select null) |
| union |
| (select 1 union select distinct null) |
| )s2); |
| |
| -- Yet, we keep behaviors on text-like columns |
| select pg_typeof(a) from(select 'foo' a union select 'foo'::name)s; |
| select pg_typeof(a) from(select 1 x, 'foo' a union |
| select 1, 'foo' union select 1, 'foo'::name)s; |
| select pg_typeof(a) from(select 1 x, 'foo' a union |
| (select 1, 'foo' union select 1, 'foo'::name))s; |
| |
| CREATE TABLE union_ctas (a, b) AS SELECT 1, 2 UNION SELECT 1, 1 UNION SELECT 1, 1; |
| SELECT * FROM union_ctas; |
| DROP TABLE union_ctas; |