-- Complex nested CTEs CREATE SCHEMA with_nested; SET search_path tO with_nested, public; CREATE TABLE with_nested.local_users (user_id int, event_type int); INSERT INTO local_users VALUES (0, 0), (1, 4), (1, 7), (2, 1), (3, 3), (5, 4), (6, 2), (10, 7); -- Can refer to outer CTE because it is recursively planned first WITH cte_1 AS ( SELECT DISTINCT user_id FROM users_table ), cte_2 AS ( WITH cte_1_1 AS ( SELECT * FROM cte_1 WHERE user_id > 1 ) SELECT * FROM cte_1_1 WHERE user_id < 3 ) SELECT user_id FROM cte_2 LIMIT 1; user_id --------------------------------------------------------------------- 2 (1 row) -- Nested CTEs WITH users_events AS ( WITH users_events_2 AS ( SELECT users_table.user_id as user_id, events_table.event_type as event_type FROM users_table, events_table WHERE users_table.user_id = events_table.user_id GROUP BY users_table.user_id, events_table.event_type ) SELECT u_events.user_id, events_table.event_type FROM users_events_2 as u_events, events_table WHERE u_events.user_id = events_table.user_id ) SELECT * FROM users_events ORDER BY 1, 2 LIMIT 20; user_id | event_type --------------------------------------------------------------------- 1 | 0 1 | 0 1 | 0 1 | 0 1 | 0 1 | 0 1 | 0 1 | 0 1 | 0 1 | 0 1 | 0 1 | 0 1 | 1 1 | 1 1 | 1 1 | 1 1 | 1 1 | 1 1 | 1 1 | 1 (20 rows) -- Nested CTEs WITH users_events AS ( WITH users_events AS ( WITH users_events AS ( WITH users_events AS ( WITH users_events AS ( WITH users_events AS ( WITH users_events AS ( SELECT users_table.user_id as user_id, events_table.event_type as event_type FROM users_table, events_table WHERE users_table.user_id = events_table.user_id GROUP BY users_table.user_id, events_table.event_type ) SELECT uid, event_type, value_2, value_3 FROM ( ( SELECT user_id as uid FROM users_events ) users join events_table on users.uid = events_table.event_type ) a ) SELECT * FROM users_events ORDER BY 1, 3, 2, 4 LIMIT 100 ) SELECT * FROM users_events LIMIT 90 ) SELECT * FROM users_events LIMIT 50 ) SELECT uid, event_type, value_2, sum(value_3) as sum_3 FROM users_events GROUP BY 1, 2, 3 LIMIT 40 ) SELECT uid, event_type, sum(value_2) as sum_2, sum(sum_3) as sum_3 FROM users_events GROUP BY 1, 2 LIMIT 30 ) SELECT uid, avg(event_type), sum(sum_2), sum(sum_3) FROM users_events GROUP BY 1; uid | avg | sum | sum --------------------------------------------------------------------- 1 | 1.00000000000000000000 | 3 | 72 (1 row) -- Nested CTEs WITH users_events AS ( -- router select query WITH users_events_1 AS ( SELECT * FROM users_table WHERE user_id = 1 ), -- real-time select query users_events_2_3 AS ( SELECT * FROM users_table WHERE user_id = 2 OR user_id = 3 ), -- router select query -- sub CTE is a real-time executor query but the top level is router select users_events_4 AS ( WITH users_events_4_5 AS ( SELECT * FROM users_table WHERE user_id = 4 OR user_id = 5 ) SELECT * FROM users_events_4_5 WHERE user_id = 4 ), -- merge all the results from CTEs merged_users AS ( SELECT * FROM users_events_1 UNION SELECT * FROM users_events_2_3 UNION SELECT * FROM users_events_4 ) SELECT * FROM merged_users ) SELECT * FROM users_events ORDER BY 1, 2, 3, 4, 5, 6 LIMIT 20; user_id | time | value_1 | value_2 | value_3 | value_4 --------------------------------------------------------------------- 1 | Wed Nov 22 22:51:43.132261 2017 | 4 | 0 | 3 | 1 | Thu Nov 23 03:32:50.803031 2017 | 3 | 2 | 1 | 1 | Thu Nov 23 09:26:42.145043 2017 | 1 | 3 | 3 | 1 | Thu Nov 23 11:11:24.40789 2017 | 3 | 4 | 0 | 1 | Thu Nov 23 11:44:57.515981 2017 | 4 | 3 | 4 | 1 | Thu Nov 23 17:23:03.441394 2017 | 5 | 4 | 3 | 1 | Thu Nov 23 17:30:34.635085 2017 | 3 | 4 | 4 | 1 | | | | | 2 | Wed Nov 22 18:19:49.944985 2017 | 3 | 5 | 1 | 2 | Thu Nov 23 00:19:14.138058 2017 | 3 | 4 | 0 | 2 | Thu Nov 23 01:04:26.198826 2017 | 4 | 3 | 4 | 2 | Thu Nov 23 01:14:27.658529 2017 | 4 | 4 | 4 | 2 | Thu Nov 23 03:27:50.327051 2017 | 2 | 2 | 0 | 2 | Thu Nov 23 06:01:08.148777 2017 | 2 | 4 | 2 | 2 | Thu Nov 23 06:23:53.572592 2017 | 4 | 4 | 5 | 2 | Thu Nov 23 06:50:30.797805 2017 | 1 | 1 | 1 | 2 | Thu Nov 23 06:56:38.46819 2017 | 0 | 1 | 3 | 2 | Thu Nov 23 08:22:22.169158 2017 | 4 | 2 | 5 | 2 | Thu Nov 23 08:49:47.029236 2017 | 4 | 2 | 4 | 2 | Thu Nov 23 09:54:28.13665 2017 | 0 | 3 | 4 | (20 rows) -- Nested CTEs - joined with local table. Not supported yet. WITH users_events AS ( -- router select query WITH users_events_1 AS ( SELECT * FROM users_table WHERE user_id = 1 ), -- real-time select query users_events_2_3 AS ( SELECT * FROM users_table WHERE user_id = 2 OR user_id = 3 ), -- router select query -- sub CTE is a real-time executor query but the top level is router select users_events_4 AS ( WITH users_events_4_5 AS ( SELECT * FROM users_table WHERE user_id = 4 OR user_id = 5 ) SELECT * FROM users_events_4_5 WHERE user_id = 4 ) -- merge all the results from CTEs SELECT * FROM users_events_1 UNION SELECT * FROM users_events_2_3 UNION SELECT * FROM users_events_4 ) SELECT * FROM users_events ORDER BY 1, 2, 3, 4, 5, 6 LIMIT 20; user_id | time | value_1 | value_2 | value_3 | value_4 --------------------------------------------------------------------- 1 | Wed Nov 22 22:51:43.132261 2017 | 4 | 0 | 3 | 1 | Thu Nov 23 03:32:50.803031 2017 | 3 | 2 | 1 | 1 | Thu Nov 23 09:26:42.145043 2017 | 1 | 3 | 3 | 1 | Thu Nov 23 11:11:24.40789 2017 | 3 | 4 | 0 | 1 | Thu Nov 23 11:44:57.515981 2017 | 4 | 3 | 4 | 1 | Thu Nov 23 17:23:03.441394 2017 | 5 | 4 | 3 | 1 | Thu Nov 23 17:30:34.635085 2017 | 3 | 4 | 4 | 1 | | | | | 2 | Wed Nov 22 18:19:49.944985 2017 | 3 | 5 | 1 | 2 | Thu Nov 23 00:19:14.138058 2017 | 3 | 4 | 0 | 2 | Thu Nov 23 01:04:26.198826 2017 | 4 | 3 | 4 | 2 | Thu Nov 23 01:14:27.658529 2017 | 4 | 4 | 4 | 2 | Thu Nov 23 03:27:50.327051 2017 | 2 | 2 | 0 | 2 | Thu Nov 23 06:01:08.148777 2017 | 2 | 4 | 2 | 2 | Thu Nov 23 06:23:53.572592 2017 | 4 | 4 | 5 | 2 | Thu Nov 23 06:50:30.797805 2017 | 1 | 1 | 1 | 2 | Thu Nov 23 06:56:38.46819 2017 | 0 | 1 | 3 | 2 | Thu Nov 23 08:22:22.169158 2017 | 4 | 2 | 5 | 2 | Thu Nov 23 08:49:47.029236 2017 | 4 | 2 | 4 | 2 | Thu Nov 23 09:54:28.13665 2017 | 0 | 3 | 4 | (20 rows) -- access to uncle, use window function, apply aggregates, use group by, LIMIT/OFFSET WITH cte1 AS ( WITH cte1_1 AS ( WITH cte1_1_1 AS ( SELECT user_id, time, value_2 FROM users_table ), cte1_1_2 AS ( SELECT user_id, count FROM ( SELECT user_id, count(value_2) OVER (PARTITION BY user_id) FROM users_table GROUP BY 1, users_table.value_2 )aa GROUP BY 1,2 ORDER BY 1,2 LIMIT 4 OFFSET 2 ) SELECT cte1_1_1.user_id, cte1_1_1.time, cte1_1_2.count FROM cte1_1_1 join cte1_1_2 on cte1_1_1.user_id=cte1_1_2.user_id ), cte1_2 AS ( WITH cte1_2_1 AS ( SELECT user_id, time, avg(value_1)::real as value_1, min(value_2) as value_2 FROM users_table GROUP BY 1, 2 ), cte1_2_2 AS ( SELECT cte1_2_1.user_id, cte1_1.time, cte1_2_1.value_1, cte1_1.count FROM cte1_2_1 join cte1_1 on cte1_2_1.time=cte1_1.time and cte1_2_1.user_id=cte1_1.user_id ) SELECT * FROM cte1_2_2 ) SELECT * FROM cte1_2 ), cte2 AS ( WITH cte2_1 AS ( WITH cte2_1_1 AS ( SELECT * FROM cte1 ) SELECT user_id, time, value_1, min(count) FROM cte2_1_1 GROUP BY 1, 2, 3 ORDER BY 1,2,3 ) SELECT * FROM cte2_1 ORDER BY 1,2,3,4 LIMIT 3 OFFSET 2 ) SELECT * FROM cte2; user_id | time | value_1 | min --------------------------------------------------------------------- 3 | Wed Nov 22 23:24:32.080584 2017 | 3 | 5 3 | Thu Nov 23 00:15:45.610845 2017 | 1 | 5 3 | Thu Nov 23 03:23:24.702501 2017 | 1 | 5 (3 rows) DROP SCHEMA with_nested CASCADE; NOTICE: drop cascades to table local_users