union.sql 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542
  1. --
  2. -- UNION (also INTERSECT, EXCEPT)
  3. --
  4. -- Simple UNION constructs
  5. SELECT 1 AS two UNION SELECT 2 ORDER BY 1;
  6. SELECT 1 AS one UNION SELECT 1 ORDER BY 1;
  7. SELECT 1 AS two UNION ALL SELECT 2;
  8. SELECT 1 AS two UNION ALL SELECT 1;
  9. SELECT 1 AS three UNION SELECT 2 UNION SELECT 3 ORDER BY 1;
  10. SELECT 1 AS two UNION SELECT 2 UNION SELECT 2 ORDER BY 1;
  11. SELECT 1 AS three UNION SELECT 2 UNION ALL SELECT 2 ORDER BY 1;
  12. SELECT 1.1 AS two UNION SELECT 2.2 ORDER BY 1;
  13. -- Mixed types
  14. SELECT 1.1 AS two UNION SELECT 2 ORDER BY 1;
  15. SELECT 1 AS two UNION SELECT 2.2 ORDER BY 1;
  16. SELECT 1 AS one UNION SELECT 1.0::float8 ORDER BY 1;
  17. SELECT 1.1 AS two UNION ALL SELECT 2 ORDER BY 1;
  18. SELECT 1.0::float8 AS two UNION ALL SELECT 1 ORDER BY 1;
  19. SELECT 1.1 AS three UNION SELECT 2 UNION SELECT 3 ORDER BY 1;
  20. SELECT 1.1::float8 AS two UNION SELECT 2 UNION SELECT 2.0::float8 ORDER BY 1;
  21. SELECT 1.1 AS three UNION SELECT 2 UNION ALL SELECT 2 ORDER BY 1;
  22. SELECT 1.1 AS two UNION (SELECT 2 UNION ALL SELECT 2) ORDER BY 1;
  23. --
  24. -- Try testing from tables...
  25. --
  26. SELECT f1 AS five FROM FLOAT8_TBL
  27. UNION
  28. SELECT f1 FROM FLOAT8_TBL
  29. ORDER BY 1;
  30. SELECT f1 AS ten FROM FLOAT8_TBL
  31. UNION ALL
  32. SELECT f1 FROM FLOAT8_TBL;
  33. SELECT f1 AS nine FROM FLOAT8_TBL
  34. UNION
  35. SELECT f1 FROM INT4_TBL
  36. ORDER BY 1;
  37. SELECT f1 AS ten FROM FLOAT8_TBL
  38. UNION ALL
  39. SELECT f1 FROM INT4_TBL;
  40. SELECT f1 AS five FROM FLOAT8_TBL
  41. WHERE f1 BETWEEN -1e6 AND 1e6
  42. UNION
  43. SELECT f1 FROM INT4_TBL
  44. WHERE f1 BETWEEN 0 AND 1000000
  45. ORDER BY 1;
  46. SELECT CAST(f1 AS char(4)) AS three FROM VARCHAR_TBL
  47. UNION
  48. SELECT f1 FROM CHAR_TBL
  49. ORDER BY 1;
  50. SELECT f1 AS three FROM VARCHAR_TBL
  51. UNION
  52. SELECT CAST(f1 AS varchar) FROM CHAR_TBL
  53. ORDER BY 1;
  54. SELECT f1 AS eight FROM VARCHAR_TBL
  55. UNION ALL
  56. SELECT f1 FROM CHAR_TBL;
  57. SELECT f1 AS five FROM TEXT_TBL
  58. UNION
  59. SELECT f1 FROM VARCHAR_TBL
  60. UNION
  61. SELECT TRIM(TRAILING FROM f1) FROM CHAR_TBL
  62. ORDER BY 1;
  63. --
  64. -- INTERSECT and EXCEPT
  65. --
  66. SELECT q2 FROM int8_tbl INTERSECT SELECT q1 FROM int8_tbl ORDER BY 1;
  67. SELECT q2 FROM int8_tbl INTERSECT ALL SELECT q1 FROM int8_tbl ORDER BY 1;
  68. SELECT q2 FROM int8_tbl EXCEPT SELECT q1 FROM int8_tbl ORDER BY 1;
  69. SELECT q2 FROM int8_tbl EXCEPT ALL SELECT q1 FROM int8_tbl ORDER BY 1;
  70. SELECT q2 FROM int8_tbl EXCEPT ALL SELECT DISTINCT q1 FROM int8_tbl ORDER BY 1;
  71. SELECT q1 FROM int8_tbl EXCEPT SELECT q2 FROM int8_tbl ORDER BY 1;
  72. SELECT q1 FROM int8_tbl EXCEPT ALL SELECT q2 FROM int8_tbl ORDER BY 1;
  73. SELECT q1 FROM int8_tbl EXCEPT ALL SELECT DISTINCT q2 FROM int8_tbl ORDER BY 1;
  74. SELECT q1 FROM int8_tbl EXCEPT ALL SELECT q1 FROM int8_tbl FOR NO KEY UPDATE;
  75. -- nested cases
  76. (SELECT 1,2,3 UNION SELECT 4,5,6) INTERSECT SELECT 4,5,6;
  77. (SELECT 1,2,3 UNION SELECT 4,5,6 ORDER BY 1,2) INTERSECT SELECT 4,5,6;
  78. (SELECT 1,2,3 UNION SELECT 4,5,6) EXCEPT SELECT 4,5,6;
  79. (SELECT 1,2,3 UNION SELECT 4,5,6 ORDER BY 1,2) EXCEPT SELECT 4,5,6;
  80. -- exercise both hashed and sorted implementations of UNION/INTERSECT/EXCEPT
  81. set enable_hashagg to on;
  82. explain (costs off)
  83. select count(*) from
  84. ( select unique1 from tenk1 union select fivethous from tenk1 ) ss;
  85. select count(*) from
  86. ( select unique1 from tenk1 union select fivethous from tenk1 ) ss;
  87. explain (costs off)
  88. select count(*) from
  89. ( select unique1 from tenk1 intersect select fivethous from tenk1 ) ss;
  90. select count(*) from
  91. ( select unique1 from tenk1 intersect select fivethous from tenk1 ) ss;
  92. explain (costs off)
  93. select unique1 from tenk1 except select unique2 from tenk1 where unique2 != 10;
  94. select unique1 from tenk1 except select unique2 from tenk1 where unique2 != 10;
  95. set enable_hashagg to off;
  96. explain (costs off)
  97. select count(*) from
  98. ( select unique1 from tenk1 union select fivethous from tenk1 ) ss;
  99. select count(*) from
  100. ( select unique1 from tenk1 union select fivethous from tenk1 ) ss;
  101. explain (costs off)
  102. select count(*) from
  103. ( select unique1 from tenk1 intersect select fivethous from tenk1 ) ss;
  104. select count(*) from
  105. ( select unique1 from tenk1 intersect select fivethous from tenk1 ) ss;
  106. explain (costs off)
  107. select unique1 from tenk1 except select unique2 from tenk1 where unique2 != 10;
  108. select unique1 from tenk1 except select unique2 from tenk1 where unique2 != 10;
  109. reset enable_hashagg;
  110. -- non-hashable type
  111. set enable_hashagg to on;
  112. explain (costs off)
  113. select x from (values (100::money), (200::money)) _(x) union select x from (values (100::money), (300::money)) _(x);
  114. set enable_hashagg to off;
  115. explain (costs off)
  116. select x from (values (100::money), (200::money)) _(x) union select x from (values (100::money), (300::money)) _(x);
  117. reset enable_hashagg;
  118. -- arrays
  119. set enable_hashagg to on;
  120. explain (costs off)
  121. select x from (values (array[1, 2]), (array[1, 3])) _(x) union select x from (values (array[1, 2]), (array[1, 4])) _(x);
  122. select x from (values (array[1, 2]), (array[1, 3])) _(x) union select x from (values (array[1, 2]), (array[1, 4])) _(x);
  123. explain (costs off)
  124. select x from (values (array[1, 2]), (array[1, 3])) _(x) intersect select x from (values (array[1, 2]), (array[1, 4])) _(x);
  125. select x from (values (array[1, 2]), (array[1, 3])) _(x) intersect select x from (values (array[1, 2]), (array[1, 4])) _(x);
  126. explain (costs off)
  127. select x from (values (array[1, 2]), (array[1, 3])) _(x) except select x from (values (array[1, 2]), (array[1, 4])) _(x);
  128. select x from (values (array[1, 2]), (array[1, 3])) _(x) except select x from (values (array[1, 2]), (array[1, 4])) _(x);
  129. -- non-hashable type
  130. explain (costs off)
  131. select x from (values (array[100::money]), (array[200::money])) _(x) union select x from (values (array[100::money]), (array[300::money])) _(x);
  132. select x from (values (array[100::money]), (array[200::money])) _(x) union select x from (values (array[100::money]), (array[300::money])) _(x);
  133. set enable_hashagg to off;
  134. explain (costs off)
  135. select x from (values (array[1, 2]), (array[1, 3])) _(x) union select x from (values (array[1, 2]), (array[1, 4])) _(x);
  136. select x from (values (array[1, 2]), (array[1, 3])) _(x) union select x from (values (array[1, 2]), (array[1, 4])) _(x);
  137. explain (costs off)
  138. select x from (values (array[1, 2]), (array[1, 3])) _(x) intersect select x from (values (array[1, 2]), (array[1, 4])) _(x);
  139. select x from (values (array[1, 2]), (array[1, 3])) _(x) intersect select x from (values (array[1, 2]), (array[1, 4])) _(x);
  140. explain (costs off)
  141. select x from (values (array[1, 2]), (array[1, 3])) _(x) except select x from (values (array[1, 2]), (array[1, 4])) _(x);
  142. select x from (values (array[1, 2]), (array[1, 3])) _(x) except select x from (values (array[1, 2]), (array[1, 4])) _(x);
  143. reset enable_hashagg;
  144. -- records
  145. set enable_hashagg to on;
  146. explain (costs off)
  147. select x from (values (row(1, 2)), (row(1, 3))) _(x) union select x from (values (row(1, 2)), (row(1, 4))) _(x);
  148. select x from (values (row(1, 2)), (row(1, 3))) _(x) union select x from (values (row(1, 2)), (row(1, 4))) _(x);
  149. explain (costs off)
  150. select x from (values (row(1, 2)), (row(1, 3))) _(x) intersect select x from (values (row(1, 2)), (row(1, 4))) _(x);
  151. select x from (values (row(1, 2)), (row(1, 3))) _(x) intersect select x from (values (row(1, 2)), (row(1, 4))) _(x);
  152. explain (costs off)
  153. select x from (values (row(1, 2)), (row(1, 3))) _(x) except select x from (values (row(1, 2)), (row(1, 4))) _(x);
  154. select x from (values (row(1, 2)), (row(1, 3))) _(x) except select x from (values (row(1, 2)), (row(1, 4))) _(x);
  155. -- non-hashable type
  156. -- With an anonymous row type, the typcache does not report that the
  157. -- type is hashable. (Otherwise, this would fail at execution time.)
  158. explain (costs off)
  159. select x from (values (row(100::money)), (row(200::money))) _(x) union select x from (values (row(100::money)), (row(300::money))) _(x);
  160. select x from (values (row(100::money)), (row(200::money))) _(x) union select x from (values (row(100::money)), (row(300::money))) _(x);
  161. -- With a defined row type, the typcache can inspect the type's fields
  162. -- for hashability.
  163. create type ct1 as (f1 money);
  164. explain (costs off)
  165. select x from (values (row(100::money)::ct1), (row(200::money)::ct1)) _(x) union select x from (values (row(100::money)::ct1), (row(300::money)::ct1)) _(x);
  166. select x from (values (row(100::money)::ct1), (row(200::money)::ct1)) _(x) union select x from (values (row(100::money)::ct1), (row(300::money)::ct1)) _(x);
  167. drop type ct1;
  168. set enable_hashagg to off;
  169. explain (costs off)
  170. select x from (values (row(1, 2)), (row(1, 3))) _(x) union select x from (values (row(1, 2)), (row(1, 4))) _(x);
  171. select x from (values (row(1, 2)), (row(1, 3))) _(x) union select x from (values (row(1, 2)), (row(1, 4))) _(x);
  172. explain (costs off)
  173. select x from (values (row(1, 2)), (row(1, 3))) _(x) intersect select x from (values (row(1, 2)), (row(1, 4))) _(x);
  174. select x from (values (row(1, 2)), (row(1, 3))) _(x) intersect select x from (values (row(1, 2)), (row(1, 4))) _(x);
  175. explain (costs off)
  176. select x from (values (row(1, 2)), (row(1, 3))) _(x) except select x from (values (row(1, 2)), (row(1, 4))) _(x);
  177. select x from (values (row(1, 2)), (row(1, 3))) _(x) except select x from (values (row(1, 2)), (row(1, 4))) _(x);
  178. reset enable_hashagg;
  179. --
  180. -- Mixed types
  181. --
  182. SELECT f1 FROM float8_tbl INTERSECT SELECT f1 FROM int4_tbl ORDER BY 1;
  183. SELECT f1 FROM float8_tbl EXCEPT SELECT f1 FROM int4_tbl ORDER BY 1;
  184. --
  185. -- Operator precedence and (((((extra))))) parentheses
  186. --
  187. SELECT q1 FROM int8_tbl INTERSECT SELECT q2 FROM int8_tbl UNION ALL SELECT q2 FROM int8_tbl ORDER BY 1;
  188. SELECT q1 FROM int8_tbl INTERSECT (((SELECT q2 FROM int8_tbl UNION ALL SELECT q2 FROM int8_tbl))) ORDER BY 1;
  189. (((SELECT q1 FROM int8_tbl INTERSECT SELECT q2 FROM int8_tbl ORDER BY 1))) UNION ALL SELECT q2 FROM int8_tbl;
  190. SELECT q1 FROM int8_tbl UNION ALL SELECT q2 FROM int8_tbl EXCEPT SELECT q1 FROM int8_tbl ORDER BY 1;
  191. SELECT q1 FROM int8_tbl UNION ALL (((SELECT q2 FROM int8_tbl EXCEPT SELECT q1 FROM int8_tbl ORDER BY 1)));
  192. (((SELECT q1 FROM int8_tbl UNION ALL SELECT q2 FROM int8_tbl))) EXCEPT SELECT q1 FROM int8_tbl ORDER BY 1;
  193. --
  194. -- Subqueries with ORDER BY & LIMIT clauses
  195. --
  196. -- In this syntax, ORDER BY/LIMIT apply to the result of the EXCEPT
  197. SELECT q1,q2 FROM int8_tbl EXCEPT SELECT q2,q1 FROM int8_tbl
  198. ORDER BY q2,q1;
  199. -- This should fail, because q2 isn't a name of an EXCEPT output column
  200. SELECT q1 FROM int8_tbl EXCEPT SELECT q2 FROM int8_tbl ORDER BY q2 LIMIT 1;
  201. -- But this should work:
  202. SELECT q1 FROM int8_tbl EXCEPT (((SELECT q2 FROM int8_tbl ORDER BY q2 LIMIT 1))) ORDER BY 1;
  203. --
  204. -- New syntaxes (7.1) permit new tests
  205. --
  206. (((((select * from int8_tbl)))));
  207. --
  208. -- Check behavior with empty select list (allowed since 9.4)
  209. --
  210. select union select;
  211. select intersect select;
  212. select except select;
  213. -- check hashed implementation
  214. set enable_hashagg = true;
  215. set enable_sort = false;
  216. explain (costs off)
  217. select from generate_series(1,5) union select from generate_series(1,3);
  218. explain (costs off)
  219. select from generate_series(1,5) intersect select from generate_series(1,3);
  220. select from generate_series(1,5) union select from generate_series(1,3);
  221. select from generate_series(1,5) union all select from generate_series(1,3);
  222. select from generate_series(1,5) intersect select from generate_series(1,3);
  223. select from generate_series(1,5) intersect all select from generate_series(1,3);
  224. select from generate_series(1,5) except select from generate_series(1,3);
  225. select from generate_series(1,5) except all select from generate_series(1,3);
  226. -- check sorted implementation
  227. set enable_hashagg = false;
  228. set enable_sort = true;
  229. explain (costs off)
  230. select from generate_series(1,5) union select from generate_series(1,3);
  231. explain (costs off)
  232. select from generate_series(1,5) intersect select from generate_series(1,3);
  233. select from generate_series(1,5) union select from generate_series(1,3);
  234. select from generate_series(1,5) union all select from generate_series(1,3);
  235. select from generate_series(1,5) intersect select from generate_series(1,3);
  236. select from generate_series(1,5) intersect all select from generate_series(1,3);
  237. select from generate_series(1,5) except select from generate_series(1,3);
  238. select from generate_series(1,5) except all select from generate_series(1,3);
  239. reset enable_hashagg;
  240. reset enable_sort;
  241. --
  242. -- Check handling of a case with unknown constants. We don't guarantee
  243. -- an undecorated constant will work in all cases, but historically this
  244. -- usage has worked, so test we don't break it.
  245. --
  246. SELECT a.f1 FROM (SELECT 'test' AS f1 FROM varchar_tbl) a
  247. UNION
  248. SELECT b.f1 FROM (SELECT f1 FROM varchar_tbl) b
  249. ORDER BY 1;
  250. -- This should fail, but it should produce an error cursor
  251. SELECT '3.4'::numeric UNION SELECT 'foo';
  252. --
  253. -- Test that expression-index constraints can be pushed down through
  254. -- UNION or UNION ALL
  255. --
  256. CREATE TEMP TABLE t1 (a text, b text);
  257. CREATE INDEX t1_ab_idx on t1 ((a || b));
  258. CREATE TEMP TABLE t2 (ab text primary key);
  259. INSERT INTO t1 VALUES ('a', 'b'), ('x', 'y');
  260. INSERT INTO t2 VALUES ('ab'), ('xy');
  261. set enable_seqscan = off;
  262. set enable_indexscan = on;
  263. set enable_bitmapscan = off;
  264. explain (costs off)
  265. SELECT * FROM
  266. (SELECT a || b AS ab FROM t1
  267. UNION ALL
  268. SELECT * FROM t2) t
  269. WHERE ab = 'ab';
  270. explain (costs off)
  271. SELECT * FROM
  272. (SELECT a || b AS ab FROM t1
  273. UNION
  274. SELECT * FROM t2) t
  275. WHERE ab = 'ab';
  276. --
  277. -- Test that ORDER BY for UNION ALL can be pushed down to inheritance
  278. -- children.
  279. --
  280. CREATE TEMP TABLE t1c (b text, a text);
  281. ALTER TABLE t1c INHERIT t1;
  282. CREATE TEMP TABLE t2c (primary key (ab)) INHERITS (t2);
  283. INSERT INTO t1c VALUES ('v', 'w'), ('c', 'd'), ('m', 'n'), ('e', 'f');
  284. INSERT INTO t2c VALUES ('vw'), ('cd'), ('mn'), ('ef');
  285. CREATE INDEX t1c_ab_idx on t1c ((a || b));
  286. set enable_seqscan = on;
  287. set enable_indexonlyscan = off;
  288. explain (costs off)
  289. SELECT * FROM
  290. (SELECT a || b AS ab FROM t1
  291. UNION ALL
  292. SELECT ab FROM t2) t
  293. ORDER BY 1 LIMIT 8;
  294. SELECT * FROM
  295. (SELECT a || b AS ab FROM t1
  296. UNION ALL
  297. SELECT ab FROM t2) t
  298. ORDER BY 1 LIMIT 8;
  299. reset enable_seqscan;
  300. reset enable_indexscan;
  301. reset enable_bitmapscan;
  302. -- This simpler variant of the above test has been observed to fail differently
  303. create table events (event_id int primary key);
  304. create table other_events (event_id int primary key);
  305. create table events_child () inherits (events);
  306. explain (costs off)
  307. select event_id
  308. from (select event_id from events
  309. union all
  310. select event_id from other_events) ss
  311. order by event_id;
  312. drop table events_child, events, other_events;
  313. reset enable_indexonlyscan;
  314. -- Test constraint exclusion of UNION ALL subqueries
  315. explain (costs off)
  316. SELECT * FROM
  317. (SELECT 1 AS t, * FROM tenk1 a
  318. UNION ALL
  319. SELECT 2 AS t, * FROM tenk1 b) c
  320. WHERE t = 2;
  321. -- Test that we push quals into UNION sub-selects only when it's safe
  322. explain (costs off)
  323. SELECT * FROM
  324. (SELECT 1 AS t, 2 AS x
  325. UNION
  326. SELECT 2 AS t, 4 AS x) ss
  327. WHERE x < 4
  328. ORDER BY x;
  329. SELECT * FROM
  330. (SELECT 1 AS t, 2 AS x
  331. UNION
  332. SELECT 2 AS t, 4 AS x) ss
  333. WHERE x < 4
  334. ORDER BY x;
  335. explain (costs off)
  336. SELECT * FROM
  337. (SELECT 1 AS t, generate_series(1,10) AS x
  338. UNION
  339. SELECT 2 AS t, 4 AS x) ss
  340. WHERE x < 4
  341. ORDER BY x;
  342. SELECT * FROM
  343. (SELECT 1 AS t, generate_series(1,10) AS x
  344. UNION
  345. SELECT 2 AS t, 4 AS x) ss
  346. WHERE x < 4
  347. ORDER BY x;
  348. explain (costs off)
  349. SELECT * FROM
  350. (SELECT 1 AS t, (random()*3)::int AS x
  351. UNION
  352. SELECT 2 AS t, 4 AS x) ss
  353. WHERE x > 3
  354. ORDER BY x;
  355. SELECT * FROM
  356. (SELECT 1 AS t, (random()*3)::int AS x
  357. UNION
  358. SELECT 2 AS t, 4 AS x) ss
  359. WHERE x > 3
  360. ORDER BY x;
  361. -- Test cases where the native ordering of a sub-select has more pathkeys
  362. -- than the outer query cares about
  363. explain (costs off)
  364. select distinct q1 from
  365. (select distinct * from int8_tbl i81
  366. union all
  367. select distinct * from int8_tbl i82) ss
  368. where q2 = q2;
  369. select distinct q1 from
  370. (select distinct * from int8_tbl i81
  371. union all
  372. select distinct * from int8_tbl i82) ss
  373. where q2 = q2;
  374. explain (costs off)
  375. select distinct q1 from
  376. (select distinct * from int8_tbl i81
  377. union all
  378. select distinct * from int8_tbl i82) ss
  379. where -q1 = q2;
  380. select distinct q1 from
  381. (select distinct * from int8_tbl i81
  382. union all
  383. select distinct * from int8_tbl i82) ss
  384. where -q1 = q2;
  385. -- Test proper handling of parameterized appendrel paths when the
  386. -- potential join qual is expensive
  387. create function expensivefunc(int) returns int
  388. language plpgsql immutable strict cost 10000
  389. as $$begin return $1; end$$;
  390. create temp table t3 as select generate_series(-1000,1000) as x;
  391. create index t3i on t3 (expensivefunc(x));
  392. analyze t3;
  393. explain (costs off)
  394. select * from
  395. (select * from t3 a union all select * from t3 b) ss
  396. join int4_tbl on f1 = expensivefunc(x);
  397. select * from
  398. (select * from t3 a union all select * from t3 b) ss
  399. join int4_tbl on f1 = expensivefunc(x);
  400. drop table t3;
  401. drop function expensivefunc(int);
  402. -- Test handling of appendrel quals that const-simplify into an AND
  403. explain (costs off)
  404. select * from
  405. (select *, 0 as x from int8_tbl a
  406. union all
  407. select *, 1 as x from int8_tbl b) ss
  408. where (x = 0) or (q1 >= q2 and q1 <= q2);
  409. select * from
  410. (select *, 0 as x from int8_tbl a
  411. union all
  412. select *, 1 as x from int8_tbl b) ss
  413. where (x = 0) or (q1 >= q2 and q1 <= q2);