-- =================================================================== -- test multi subquery functionality for window functions -- =================================================================== CREATE VIEW subq AS SELECT DISTINCT user_id, rank() OVER (PARTITION BY user_id ORDER BY value_1) FROM users_table GROUP BY user_id, value_1 HAVING count(*) > 1; SELECT user_id, time, rnk FROM ( SELECT *, rank() OVER my_win as rnk FROM events_table WINDOW my_win AS (PARTITION BY user_id ORDER BY time DESC) ) as foo ORDER BY 3 DESC, 1 DESC, 2 DESC LIMIT 10; user_id | time | rnk --------------------------------------------------------------------- 2 | Wed Nov 22 20:16:16.614779 2017 | 24 2 | Wed Nov 22 22:06:12.107108 2017 | 23 2 | Wed Nov 22 22:23:25.40611 2017 | 22 3 | Wed Nov 22 18:36:16.372893 2017 | 21 2 | Wed Nov 22 22:50:33.855696 2017 | 21 3 | Wed Nov 22 20:23:46.906523 2017 | 20 2 | Wed Nov 22 22:56:47.673504 2017 | 20 3 | Wed Nov 22 21:12:24.542921 2017 | 19 2 | Thu Nov 23 01:08:57.24208 2017 | 19 3 | Wed Nov 22 21:26:21.185134 2017 | 18 (10 rows) -- the same test with different syntax SELECT user_id, time, rnk FROM ( SELECT *, rank() OVER (PARTITION BY user_id ORDER BY time DESC) as rnk FROM events_table ) as foo ORDER BY 3 DESC, 1 DESC, 2 DESC LIMIT 10; user_id | time | rnk --------------------------------------------------------------------- 2 | Wed Nov 22 20:16:16.614779 2017 | 24 2 | Wed Nov 22 22:06:12.107108 2017 | 23 2 | Wed Nov 22 22:23:25.40611 2017 | 22 3 | Wed Nov 22 18:36:16.372893 2017 | 21 2 | Wed Nov 22 22:50:33.855696 2017 | 21 3 | Wed Nov 22 20:23:46.906523 2017 | 20 2 | Wed Nov 22 22:56:47.673504 2017 | 20 3 | Wed Nov 22 21:12:24.542921 2017 | 19 2 | Thu Nov 23 01:08:57.24208 2017 | 19 3 | Wed Nov 22 21:26:21.185134 2017 | 18 (10 rows) -- similar test with lag SELECT user_id, time, lag_event_type, row_no FROM ( SELECT *, lag(event_type) OVER my_win as lag_event_type, row_number() OVER my_win as row_no FROM events_table WINDOW my_win AS (PARTITION BY user_id ORDER BY time DESC) ) as foo ORDER BY 4 DESC, 3 DESC NULLS LAST, 1 DESC, 2 DESC LIMIT 10; user_id | time | lag_event_type | row_no --------------------------------------------------------------------- 2 | Wed Nov 22 20:16:16.614779 2017 | 0 | 24 2 | Wed Nov 22 22:06:12.107108 2017 | 3 | 23 2 | Wed Nov 22 22:23:25.40611 2017 | 4 | 22 2 | Wed Nov 22 22:50:33.855696 2017 | 4 | 21 3 | Wed Nov 22 18:36:16.372893 2017 | 3 | 21 2 | Wed Nov 22 22:56:47.673504 2017 | 2 | 20 3 | Wed Nov 22 20:23:46.906523 2017 | 1 | 20 2 | Thu Nov 23 01:08:57.24208 2017 | 3 | 19 3 | Wed Nov 22 21:12:24.542921 2017 | 1 | 19 3 | Wed Nov 22 21:26:21.185134 2017 | 3 | 18 (10 rows) -- simple window function, partitioned and grouped by on the distribution key SELECT user_id, rnk, avg_val_2 FROM ( SELECT user_id, rank() OVER my_win as rnk, avg(value_2) as avg_val_2 FROM events_table GROUP BY user_id, date_trunc('day', time) WINDOW my_win AS (PARTITION BY user_id ORDER BY avg(event_type) DESC) ) as foo ORDER BY 2 DESC, 1 DESC, 3 DESC LIMIT 10; user_id | rnk | avg_val_2 --------------------------------------------------------------------- 6 | 2 | 2.0000000000000000 5 | 2 | 2.0909090909090909 4 | 2 | 2.4000000000000000 3 | 2 | 3.1666666666666667 2 | 2 | 2.0000000000000000 1 | 2 | 2.1428571428571429 6 | 1 | 2.5000000000000000 5 | 1 | 2.6666666666666667 4 | 1 | 2.5000000000000000 3 | 1 | 1.8000000000000000 (10 rows) -- top level query has a group by on the result of the window function SELECT min(user_id), min(time), lag_event_type, count(*) FROM ( SELECT *, lag(event_type) OVER my_win as lag_event_type FROM events_table WINDOW my_win AS (PARTITION BY user_id ORDER BY time DESC) ) as foo GROUP BY lag_event_type ORDER BY 3 DESC NULLS LAST, 1 DESC, 2 DESC LIMIT 10; min | min | lag_event_type | count --------------------------------------------------------------------- 1 | Thu Nov 23 11:09:38.074595 2017 | 6 | 1 2 | Wed Nov 22 19:00:10.396739 2017 | 5 | 7 1 | Wed Nov 22 18:49:42.327403 2017 | 4 | 21 1 | Wed Nov 22 18:36:16.372893 2017 | 3 | 21 1 | Wed Nov 22 19:07:03.846437 2017 | 2 | 17 1 | Wed Nov 22 19:03:01.772353 2017 | 1 | 23 1 | Wed Nov 22 20:16:16.614779 2017 | 0 | 5 1 | Thu Nov 23 14:00:13.20013 2017 | | 6 (8 rows) -- window functions should work along with joins as well SELECT * FROM ( SELECT DISTINCT users_table.user_id, lag(users_table.user_id) OVER w1, rank() OVER w1 FROM users_table, events_table WHERE users_table.user_id = events_table.user_id and event_type < 4 WINDOW w1 AS (PARTITION BY users_table.user_id, events_table.event_type ORDER BY events_table.time) ) as foo ORDER BY 3 DESC, 1 DESC, 2 DESC NULLS LAST LIMIT 10; user_id | lag | rank --------------------------------------------------------------------- 2 | 2 | 109 5 | 5 | 105 3 | 3 | 103 2 | 2 | 91 3 | 3 | 86 5 | 5 | 79 2 | 2 | 73 4 | 4 | 70 3 | 3 | 69 2 | 2 | 55 (10 rows) -- two window functions in a single subquery should work fine as well SELECT * FROM ( SELECT DISTINCT users_table.user_id, lag(users_table.user_id) OVER w1, rank() OVER w2 FROM users_table, events_table WHERE users_table.user_id = events_table.user_id and event_type < 4 WINDOW w1 AS (PARTITION BY users_table.user_id, events_table.event_type ORDER BY events_table.time), w2 AS (PARTITION BY users_table.user_id, (events_table.value_2 % 25) ORDER BY events_table.time) ) as foo ORDER BY 3 DESC, 1 DESC, 2 DESC NULLS LAST LIMIT 10; user_id | lag | rank --------------------------------------------------------------------- 2 | 2 | 73 4 | 4 | 70 3 | 3 | 69 2 | 2 | 55 5 | 5 | 53 5 | | 53 3 | 3 | 52 4 | 4 | 47 2 | 2 | 37 3 | 3 | 35 (10 rows) -- window functions should be fine within subquery joins SELECT sub_1.user_id, max(lag_1), max(rank_1), max(rank_2) FROM ( SELECT DISTINCT users_table.user_id, lag(users_table.user_id) OVER w1 as lag_1, rank() OVER w2 as rank_1 FROM users_table, events_table WHERE users_table.user_id = events_table.user_id and event_type < 4 WINDOW w1 AS (PARTITION BY users_table.user_id, events_table.event_type ORDER BY events_table.time), w2 AS (PARTITION BY users_table.user_id, (events_table.value_2 % 25) ORDER BY events_table.time) ) as sub_1 JOIN ( SELECT DISTINCT users_table.user_id, lag(users_table.user_id) OVER w1 as lag_2, rank() OVER w2 as rank_2 FROM users_table, events_table WHERE users_table.user_id = events_table.user_id and event_type < 4 WINDOW w1 AS (PARTITION BY users_table.user_id, events_table.value_2 ORDER BY events_table.time), w2 AS (PARTITION BY users_table.user_id, (events_table.value_2 % 50) ORDER BY events_table.time) ) as sub_2 ON(sub_1.user_id = sub_2.user_id) GROUP BY sub_1.user_id ORDER BY 3 DESC, 4 DESC, 1 DESC, 2 DESC NULLS LAST LIMIT 10; user_id | max | max | max --------------------------------------------------------------------- 2 | 2 | 73 | 73 4 | 4 | 70 | 70 3 | 3 | 69 | 69 5 | 5 | 53 | 53 6 | 6 | 21 | 21 1 | 1 | 15 | 15 (6 rows) -- GROUP BYs and PARTITION BYs should work fine together SELECT avg(user_id), max(time), my_rank FROM ( SELECT user_id, date_trunc('day', time) as time, rank() OVER my_win as my_rank FROM events_table GROUP BY user_id, date_trunc('day', time) WINDOW my_win AS (PARTITION BY user_id ORDER BY count(*) DESC) ) as foo WHERE my_rank > 1 GROUP BY my_rank ORDER BY 3 DESC, 1 DESC,2 DESC LIMIT 10; avg | max | my_rank --------------------------------------------------------------------- 3.5000000000000000 | Wed Nov 22 00:00:00 2017 | 2 (1 row) -- aggregates in the PARTITION BY is also allows SELECT avg(user_id), max(time), my_rank FROM ( SELECT user_id, date_trunc('day', time) as time, rank() OVER my_win as my_rank FROM events_table GROUP BY user_id, date_trunc('day', time) WINDOW my_win AS (PARTITION BY user_id, avg(event_type%3)::int ORDER BY count(*) DESC) ) as foo WHERE my_rank > 0 GROUP BY my_rank ORDER BY 3 DESC, 1 DESC,2 DESC LIMIT 10; avg | max | my_rank --------------------------------------------------------------------- 3.7500000000000000 | Wed Nov 22 00:00:00 2017 | 2 3.3750000000000000 | Thu Nov 23 00:00:00 2017 | 1 (2 rows) -- GROUP BY should not necessarly be inclusive of partitioning -- but this query doesn't make much sense SELECT avg(user_id), my_rank FROM ( SELECT user_id, rank() OVER my_win as my_rank FROM events_table GROUP BY user_id WINDOW my_win AS (PARTITION BY user_id, max(event_type) ORDER BY count(*) DESC) ) as foo GROUP BY my_rank ORDER BY 2 DESC, 1 DESC LIMIT 10; avg | my_rank --------------------------------------------------------------------- 3.5000000000000000 | 1 (1 row) -- Using previously defined supported window function on distribution key SELECT * FROM ( SELECT user_id, date_trunc('day', time) as time, sum(rank) OVER w2 FROM ( SELECT DISTINCT user_id as user_id, time, rank() over w1 FROM users_table WINDOW w AS (PARTITION BY user_id), w1 AS (w ORDER BY value_2, value_3) ) fab WINDOW w2 as (PARTITION BY user_id, time) ) a ORDER BY 1, 2, 3 DESC LIMIT 10; user_id | time | sum --------------------------------------------------------------------- 1 | Wed Nov 22 00:00:00 2017 | 1 1 | Thu Nov 23 00:00:00 2017 | 7 1 | Thu Nov 23 00:00:00 2017 | 6 1 | Thu Nov 23 00:00:00 2017 | 5 1 | Thu Nov 23 00:00:00 2017 | 4 1 | Thu Nov 23 00:00:00 2017 | 3 1 | Thu Nov 23 00:00:00 2017 | 2 2 | Wed Nov 22 00:00:00 2017 | 17 2 | Thu Nov 23 00:00:00 2017 | 18 2 | Thu Nov 23 00:00:00 2017 | 16 (10 rows) -- test with reference table partitioned on columns from both SELECT * FROM ( SELECT DISTINCT user_id, it_name, count(id) OVER (PARTITION BY user_id, id) FROM users_table, users_ref_test_table WHERE users_table.value_2 + 40 = users_ref_test_table.k_no ) a ORDER BY 1, 2, 3 LIMIT 20; user_id | it_name | count --------------------------------------------------------------------- 2 | User_1 | 2 3 | User_1 | 6 4 | User_1 | 2 5 | User_1 | 3 (4 rows) -- Group by has more columns than partition by SELECT * FROM ( SELECT DISTINCT user_id, SUM(value_2) OVER (PARTITION BY user_id) FROM users_table GROUP BY user_id, value_1, value_2 ) a ORDER BY 2 DESC, 1 LIMIT 10; user_id | sum --------------------------------------------------------------------- 3 | 44 5 | 43 4 | 41 2 | 38 1 | 16 6 | 16 (6 rows) SELECT user_id, max(sum) FROM ( SELECT user_id, SUM(value_2) OVER (PARTITION BY user_id, value_1) FROM users_table GROUP BY user_id, value_1, value_2 ) a GROUP BY user_id ORDER BY 2 DESC,1 LIMIT 10; user_id | max --------------------------------------------------------------------- 3 | 15 4 | 13 2 | 10 5 | 10 6 | 7 1 | 6 (6 rows) -- Window functions with HAVING clause SELECT * FROM ( SELECT DISTINCT user_id, rank() OVER (PARTITION BY user_id ORDER BY value_1) FROM users_table GROUP BY user_id, value_1 HAVING count(*) > 1 ) a ORDER BY 2 DESC, 1 LIMIT 10; user_id | rank --------------------------------------------------------------------- 5 | 6 2 | 5 4 | 5 5 | 5 2 | 4 3 | 4 4 | 4 5 | 4 6 | 4 2 | 3 (10 rows) -- Window function in View works SELECT * FROM subq ORDER BY 2 DESC, 1 LIMIT 10; user_id | rank --------------------------------------------------------------------- 5 | 6 2 | 5 4 | 5 5 | 5 2 | 4 3 | 4 4 | 4 5 | 4 6 | 4 2 | 3 (10 rows) -- Window functions with UNION/UNION ALL works SELECT max(avg) FROM ( (SELECT avg(value_3) over (partition by user_id), user_id FROM events_table where event_type IN (1, 2)) UNION ALL (SELECT avg(value_3) over (partition by user_id), user_id FROM events_table where event_type IN (2, 3)) UNION ALL (SELECT avg(value_3) over (partition by user_id), user_id FROM events_table where event_type IN (3, 4)) UNION ALL (SELECT avg(value_3) over (partition by user_id), user_id FROM events_table where event_type IN (4, 5)) UNION ALL (SELECT avg(value_3) over (partition by user_id), user_id FROM events_table where event_type IN (5, 6)) UNION ALL (SELECT avg(value_3) over (partition by user_id), user_id FROM events_table where event_type IN (1, 6)) ) b GROUP BY user_id ORDER BY 1 DESC LIMIT 5; max --------------------------------------------------------------------- 5 3.5 3.25 3 3 (5 rows) SELECT * FROM ( ( SELECT user_id, sum(counter) FROM (SELECT user_id, sum(value_2) over (partition by user_id) AS counter FROM users_table UNION SELECT user_id, sum(value_2) over (partition by user_id) AS counter FROM events_table) user_id_1 GROUP BY user_id) UNION (SELECT user_id, sum(counter) FROM (SELECT user_id, sum(value_2) over (partition by user_id) AS counter FROM users_table UNION SELECT user_id, sum(value_2) over (partition by user_id) AS counter FROM events_table) user_id_2 GROUP BY user_id)) AS ftop ORDER BY 2 DESC, 1 DESC LIMIT 5; user_id | sum --------------------------------------------------------------------- 2 | 107 3 | 101 5 | 94 4 | 91 1 | 62 (5 rows) -- Subquery in where with window function SELECT user_id FROM users_table WHERE value_2 > 1 AND value_2 < ALL ( SELECT avg(value_3) OVER (PARTITION BY user_id) FROM events_table WHERE users_table.user_id = events_table.user_id ) GROUP BY user_id ORDER BY user_id DESC LIMIT 3; user_id --------------------------------------------------------------------- 4 3 2 (3 rows) -- Some more nested queries SELECT user_id, rank, SUM(ABS(value_2 - value_3)) AS difference, COUNT(*) AS distinct_users FROM ( SELECT *, rank() OVER (PARTITION BY user_id ORDER BY value_2 DESC) FROM ( SELECT user_id, value_2, sum(value_3) OVER (PARTITION BY user_id, value_2) as value_3 FROM users_table ) AS A ) AS A GROUP BY user_id, rank ORDER BY difference DESC, rank DESC, user_id LIMIT 20; user_id | rank | difference | distinct_users --------------------------------------------------------------------- 4 | 12 | 306 | 9 5 | 12 | 136 | 8 3 | 1 | 84 | 6 5 | 20 | 70 | 5 3 | 11 | 55 | 5 2 | 11 | 44 | 4 2 | 3 | 40 | 5 5 | 7 | 30 | 5 2 | 8 | 24 | 3 4 | 21 | 21 | 3 2 | 15 | 21 | 3 5 | 4 | 21 | 3 6 | 9 | 20 | 2 4 | 3 | 15 | 5 3 | 16 | 14 | 2 4 | 8 | 9 | 3 1 | 1 | 9 | 3 5 | 1 | 9 | 3 6 | 7 | 8 | 2 1 | 4 | 8 | 2 (20 rows) SELECT * FROM ( SELECT DISTINCT f3.user_id, ABS(f2.sum - f3.sum) FROM ( SELECT DISTINCT user_id, sum(value_3) OVER (PARTITION BY user_id) FROM users_table GROUP BY user_id, value_3 ) f3, ( SELECT DISTINCT user_id, sum(value_2) OVER (PARTITION BY user_id) FROM users_table GROUP BY user_id, value_2 ) f2 WHERE f3.user_id=f2.user_id ) a ORDER BY abs DESC, user_id LIMIT 10; user_id | abs --------------------------------------------------------------------- 6 | 2 1 | 1 2 | 0 3 | 0 4 | 0 5 | 0 (6 rows) -- Partition by with aggregate functions. This query does not make much sense since the -- result of aggregate function will be the same for every row in a partition and it is -- not going to affect the group that the count function will work on. SELECT * FROM ( SELECT user_id, COUNT(*) OVER (PARTITION BY user_id, MIN(value_2)) FROM users_table GROUP BY 1 ) a ORDER BY 1 DESC LIMIT 5; user_id | count --------------------------------------------------------------------- 6 | 1 5 | 1 4 | 1 3 | 1 2 | 1 (5 rows) EXPLAIN (COSTS FALSE, VERBOSE TRUE) SELECT * FROM ( ( SELECT user_id, sum(counter) FROM (SELECT user_id, sum(value_2) over (partition by user_id) AS counter FROM users_table UNION SELECT user_id, sum(value_2) over (partition by user_id) AS counter FROM events_table) user_id_1 GROUP BY user_id) UNION (SELECT user_id, sum(counter) FROM (SELECT user_id, sum(value_2) over (partition by user_id) AS counter FROM users_table UNION SELECT user_id, sum(value_2) over (partition by user_id) AS counter FROM events_table) user_id_2 GROUP BY user_id)) AS ftop ORDER BY 2 DESC, 1 DESC LIMIT 5; QUERY PLAN --------------------------------------------------------------------- Limit Output: remote_scan.user_id, remote_scan.sum -> Sort Output: remote_scan.user_id, remote_scan.sum Sort Key: remote_scan.sum DESC, remote_scan.user_id DESC -> Custom Scan (Citus Adaptive) Output: remote_scan.user_id, remote_scan.sum Task Count: 4 Tasks Shown: One of 4 -> Task Query: SELECT worker_column_1 AS user_id, worker_column_2 AS sum FROM (SELECT ftop.user_id AS worker_column_1, ftop.sum AS worker_column_2 FROM (SELECT user_id_1.user_id, sum(user_id_1.counter) AS sum FROM (SELECT users_table.user_id, sum(users_table.value_2) OVER (PARTITION BY users_table.user_id) AS counter FROM public.users_table_1400256 users_table UNION SELECT events_table.user_id, sum(events_table.value_2) OVER (PARTITION BY events_table.user_id) AS counter FROM public.events_table_1400260 events_table) user_id_1 GROUP BY user_id_1.user_id UNION SELECT user_id_2.user_id, sum(user_id_2.counter) AS sum FROM (SELECT users_table.user_id, sum(users_table.value_2) OVER (PARTITION BY users_table.user_id) AS counter FROM public.users_table_1400256 users_table UNION SELECT events_table.user_id, sum(events_table.value_2) OVER (PARTITION BY events_table.user_id) AS counter FROM public.events_table_1400260 events_table) user_id_2 GROUP BY user_id_2.user_id) ftop) worker_subquery ORDER BY worker_column_2 DESC, worker_column_1 DESC LIMIT '5'::bigint Node: host=localhost port=xxxxx dbname=regression -> Limit Output: users_table.user_id, (sum((sum(users_table.value_2) OVER (?)))) -> Sort Output: users_table.user_id, (sum((sum(users_table.value_2) OVER (?)))) Sort Key: (sum((sum(users_table.value_2) OVER (?)))) DESC, users_table.user_id DESC -> HashAggregate Output: users_table.user_id, (sum((sum(users_table.value_2) OVER (?)))) Group Key: users_table.user_id, (sum((sum(users_table.value_2) OVER (?)))) -> Append -> HashAggregate Output: users_table.user_id, sum((sum(users_table.value_2) OVER (?))) Group Key: users_table.user_id -> HashAggregate Output: users_table.user_id, (sum(users_table.value_2) OVER (?)) Group Key: users_table.user_id, (sum(users_table.value_2) OVER (?)) -> Append -> WindowAgg Output: users_table.user_id, sum(users_table.value_2) OVER (?) -> Sort Output: users_table.user_id, users_table.value_2 Sort Key: users_table.user_id -> Seq Scan on public.users_table_1400256 users_table Output: users_table.user_id, users_table.value_2 -> WindowAgg Output: events_table.user_id, sum(events_table.value_2) OVER (?) -> Sort Output: events_table.user_id, events_table.value_2 Sort Key: events_table.user_id -> Seq Scan on public.events_table_1400260 events_table Output: events_table.user_id, events_table.value_2 -> HashAggregate Output: users_table_1.user_id, sum((sum(users_table_1.value_2) OVER (?))) Group Key: users_table_1.user_id -> HashAggregate Output: users_table_1.user_id, (sum(users_table_1.value_2) OVER (?)) Group Key: users_table_1.user_id, (sum(users_table_1.value_2) OVER (?)) -> Append -> WindowAgg Output: users_table_1.user_id, sum(users_table_1.value_2) OVER (?) -> Sort Output: users_table_1.user_id, users_table_1.value_2 Sort Key: users_table_1.user_id -> Seq Scan on public.users_table_1400256 users_table_1 Output: users_table_1.user_id, users_table_1.value_2 -> WindowAgg Output: events_table_1.user_id, sum(events_table_1.value_2) OVER (?) -> Sort Output: events_table_1.user_id, events_table_1.value_2 Sort Key: events_table_1.user_id -> Seq Scan on public.events_table_1400260 events_table_1 Output: events_table_1.user_id, events_table_1.value_2 (63 rows) -- test with window functions which aren't pushed down SELECT user_id, time, rnk FROM ( SELECT *, rank() OVER my_win as rnk FROM events_table WINDOW my_win AS (PARTITION BY event_type ORDER BY time DESC) ) as foo ORDER BY 3 DESC, 1 DESC, 2 DESC LIMIT 10; user_id | time | rnk --------------------------------------------------------------------- 1 | Wed Nov 22 19:07:03.846437 2017 | 24 5 | Wed Nov 22 20:45:35.99031 2017 | 23 1 | Wed Nov 22 18:49:42.327403 2017 | 23 3 | Wed Nov 22 21:12:24.542921 2017 | 22 3 | Wed Nov 22 20:23:46.906523 2017 | 22 6 | Wed Nov 22 20:36:09.106561 2017 | 21 3 | Wed Nov 22 21:26:21.185134 2017 | 21 1 | Wed Nov 22 19:03:01.772353 2017 | 21 6 | Wed Nov 22 22:44:48.458334 2017 | 20 3 | Wed Nov 22 22:05:38.409323 2017 | 20 (10 rows) SELECT user_id, time, rnk FROM ( SELECT *, rank() OVER my_win as rnk FROM events_table WINDOW my_win AS () ) as foo ORDER BY 3 DESC, 1 DESC, 2 DESC LIMIT 10; user_id | time | rnk --------------------------------------------------------------------- 6 | Thu Nov 23 14:00:13.20013 2017 | 1 6 | Thu Nov 23 11:16:13.106691 2017 | 1 6 | Thu Nov 23 07:27:32.822068 2017 | 1 6 | Thu Nov 23 02:06:53.132461 2017 | 1 6 | Thu Nov 23 00:45:41.784391 2017 | 1 6 | Thu Nov 23 00:01:48.155345 2017 | 1 6 | Wed Nov 22 23:15:15.875499 2017 | 1 6 | Wed Nov 22 22:44:48.458334 2017 | 1 6 | Wed Nov 22 21:17:09.549341 2017 | 1 6 | Wed Nov 22 20:36:09.106561 2017 | 1 (10 rows) SELECT user_id, time, rnk FROM ( SELECT *, rank() OVER my_win as rnk FROM events_table WINDOW my_win AS (ORDER BY time DESC) ) as foo ORDER BY 3 DESC, 1 DESC, 2 DESC LIMIT 10; user_id | time | rnk --------------------------------------------------------------------- 3 | Wed Nov 22 18:36:16.372893 2017 | 101 1 | Wed Nov 22 18:49:42.327403 2017 | 100 4 | Wed Nov 22 19:00:10.396739 2017 | 99 1 | Wed Nov 22 19:03:01.772353 2017 | 98 1 | Wed Nov 22 19:07:03.846437 2017 | 97 2 | Wed Nov 22 20:16:16.614779 2017 | 96 3 | Wed Nov 22 20:23:46.906523 2017 | 95 6 | Wed Nov 22 20:36:09.106561 2017 | 94 5 | Wed Nov 22 20:45:35.99031 2017 | 93 1 | Wed Nov 22 20:56:21.122638 2017 | 92 (10 rows) SELECT * FROM ( SELECT DISTINCT users_table.user_id, lag(users_table.user_id) OVER w1, rank() OVER w2 FROM users_table, events_table WHERE users_table.user_id = events_table.user_id and event_type < 4 WINDOW w1 AS (PARTITION BY users_table.user_id, events_table.event_type ORDER BY events_table.time), w2 AS (PARTITION BY users_table.user_id+1, (events_table.value_2 % 25) ORDER BY events_table.time) ) as foo ORDER BY 3 DESC, 1 DESC, 2 DESC NULLS LAST LIMIT 10; user_id | lag | rank --------------------------------------------------------------------- 2 | 2 | 73 4 | 4 | 70 3 | 3 | 69 2 | 2 | 55 5 | 5 | 53 5 | | 53 3 | 3 | 52 4 | 4 | 47 2 | 2 | 37 3 | 3 | 35 (10 rows) SELECT * FROM ( SELECT DISTINCT users_table.user_id, lag(users_table.user_id) OVER w1, rank() OVER w2 FROM users_table, events_table WHERE users_table.user_id = events_table.user_id and event_type < 4 WINDOW w1 AS (PARTITION BY users_table.user_id, events_table.event_type ORDER BY events_table.time), w2 AS (ORDER BY events_table.time) ) as foo ORDER BY 3 DESC, 1 DESC, 2 DESC NULLS LAST LIMIT 10; user_id | lag | rank --------------------------------------------------------------------- 4 | 4 | 1262 3 | 3 | 1245 2 | 2 | 1227 4 | 4 | 1204 4 | | 1204 5 | 5 | 1178 5 | 5 | 1152 5 | 5 | 1126 4 | 4 | 1103 2 | 2 | 1085 (10 rows) SELECT user_id, time, my_rank FROM ( SELECT user_id, date_trunc('day', time) as time, rank() OVER my_win as my_rank FROM events_table GROUP BY user_id, date_trunc('day', time) WINDOW my_win AS (ORDER BY avg(event_type)) ) as foo WHERE my_rank > 1 ORDER BY 3 DESC, 1 DESC,2 DESC LIMIT 10; user_id | time | my_rank --------------------------------------------------------------------- 4 | Wed Nov 22 00:00:00 2017 | 12 6 | Wed Nov 22 00:00:00 2017 | 11 5 | Wed Nov 22 00:00:00 2017 | 10 6 | Thu Nov 23 00:00:00 2017 | 9 3 | Thu Nov 23 00:00:00 2017 | 8 1 | Thu Nov 23 00:00:00 2017 | 7 1 | Wed Nov 22 00:00:00 2017 | 6 2 | Thu Nov 23 00:00:00 2017 | 5 4 | Thu Nov 23 00:00:00 2017 | 4 2 | Wed Nov 22 00:00:00 2017 | 3 (10 rows) SELECT user_id, time, my_rank FROM ( SELECT user_id, date_trunc('day', time) as time, rank() OVER my_win as my_rank FROM events_table GROUP BY user_id, date_trunc('day', time) WINDOW my_win AS (PARTITION BY date_trunc('day', time) ORDER BY avg(event_type)) ) as foo WHERE my_rank > 1 ORDER BY 3 DESC, 1 DESC,2 DESC LIMIT 10; user_id | time | my_rank --------------------------------------------------------------------- 6 | Thu Nov 23 00:00:00 2017 | 6 4 | Wed Nov 22 00:00:00 2017 | 6 6 | Wed Nov 22 00:00:00 2017 | 5 3 | Thu Nov 23 00:00:00 2017 | 5 5 | Wed Nov 22 00:00:00 2017 | 4 1 | Thu Nov 23 00:00:00 2017 | 4 2 | Thu Nov 23 00:00:00 2017 | 3 1 | Wed Nov 22 00:00:00 2017 | 3 4 | Thu Nov 23 00:00:00 2017 | 2 2 | Wed Nov 22 00:00:00 2017 | 2 (10 rows) SELECT * FROM ( SELECT user_id, date_trunc('day', time) as time, sum(rank) OVER w2 FROM ( SELECT DISTINCT user_id as user_id, time, rank() over w1 FROM users_table WINDOW w AS (PARTITION BY time), w1 AS (w ORDER BY value_2, value_3) ) fab WINDOW w2 as (PARTITION BY user_id, time) ) a ORDER BY 1,2,3; user_id | time | sum --------------------------------------------------------------------- 1 | Wed Nov 22 00:00:00 2017 | 1 1 | Thu Nov 23 00:00:00 2017 | 1 1 | Thu Nov 23 00:00:00 2017 | 1 1 | Thu Nov 23 00:00:00 2017 | 1 1 | Thu Nov 23 00:00:00 2017 | 1 1 | Thu Nov 23 00:00:00 2017 | 1 1 | Thu Nov 23 00:00:00 2017 | 1 2 | Wed Nov 22 00:00:00 2017 | 1 2 | Thu Nov 23 00:00:00 2017 | 1 2 | Thu Nov 23 00:00:00 2017 | 1 2 | Thu Nov 23 00:00:00 2017 | 1 2 | Thu Nov 23 00:00:00 2017 | 1 2 | Thu Nov 23 00:00:00 2017 | 1 2 | Thu Nov 23 00:00:00 2017 | 1 2 | Thu Nov 23 00:00:00 2017 | 1 2 | Thu Nov 23 00:00:00 2017 | 1 2 | Thu Nov 23 00:00:00 2017 | 1 2 | Thu Nov 23 00:00:00 2017 | 1 2 | Thu Nov 23 00:00:00 2017 | 1 2 | Thu Nov 23 00:00:00 2017 | 1 2 | Thu Nov 23 00:00:00 2017 | 1 2 | Thu Nov 23 00:00:00 2017 | 1 2 | Thu Nov 23 00:00:00 2017 | 1 2 | Thu Nov 23 00:00:00 2017 | 1 2 | Thu Nov 23 00:00:00 2017 | 1 3 | Wed Nov 22 00:00:00 2017 | 1 3 | Wed Nov 22 00:00:00 2017 | 1 3 | Wed Nov 22 00:00:00 2017 | 1 3 | Thu Nov 23 00:00:00 2017 | 1 3 | Thu Nov 23 00:00:00 2017 | 1 3 | Thu Nov 23 00:00:00 2017 | 1 3 | Thu Nov 23 00:00:00 2017 | 1 3 | Thu Nov 23 00:00:00 2017 | 1 3 | Thu Nov 23 00:00:00 2017 | 1 3 | Thu Nov 23 00:00:00 2017 | 1 3 | Thu Nov 23 00:00:00 2017 | 1 3 | Thu Nov 23 00:00:00 2017 | 1 3 | Thu Nov 23 00:00:00 2017 | 1 3 | Thu Nov 23 00:00:00 2017 | 1 3 | Thu Nov 23 00:00:00 2017 | 1 3 | Thu Nov 23 00:00:00 2017 | 1 3 | Thu Nov 23 00:00:00 2017 | 1 4 | Wed Nov 22 00:00:00 2017 | 1 4 | Wed Nov 22 00:00:00 2017 | 1 4 | Wed Nov 22 00:00:00 2017 | 1 4 | Thu Nov 23 00:00:00 2017 | 1 4 | Thu Nov 23 00:00:00 2017 | 1 4 | Thu Nov 23 00:00:00 2017 | 1 4 | Thu Nov 23 00:00:00 2017 | 1 4 | Thu Nov 23 00:00:00 2017 | 1 4 | Thu Nov 23 00:00:00 2017 | 1 4 | Thu Nov 23 00:00:00 2017 | 1 4 | Thu Nov 23 00:00:00 2017 | 1 4 | Thu Nov 23 00:00:00 2017 | 1 4 | Thu Nov 23 00:00:00 2017 | 1 4 | Thu Nov 23 00:00:00 2017 | 1 4 | Thu Nov 23 00:00:00 2017 | 1 4 | Thu Nov 23 00:00:00 2017 | 1 4 | Thu Nov 23 00:00:00 2017 | 1 4 | Thu Nov 23 00:00:00 2017 | 1 4 | Thu Nov 23 00:00:00 2017 | 1 4 | Thu Nov 23 00:00:00 2017 | 1 4 | Thu Nov 23 00:00:00 2017 | 1 4 | Thu Nov 23 00:00:00 2017 | 1 4 | Thu Nov 23 00:00:00 2017 | 1 5 | Wed Nov 22 00:00:00 2017 | 1 5 | Wed Nov 22 00:00:00 2017 | 1 5 | Wed Nov 22 00:00:00 2017 | 1 5 | Wed Nov 22 00:00:00 2017 | 1 5 | Wed Nov 22 00:00:00 2017 | 1 5 | Thu Nov 23 00:00:00 2017 | 1 5 | Thu Nov 23 00:00:00 2017 | 1 5 | Thu Nov 23 00:00:00 2017 | 1 5 | Thu Nov 23 00:00:00 2017 | 1 5 | Thu Nov 23 00:00:00 2017 | 1 5 | Thu Nov 23 00:00:00 2017 | 1 5 | Thu Nov 23 00:00:00 2017 | 1 5 | Thu Nov 23 00:00:00 2017 | 1 5 | Thu Nov 23 00:00:00 2017 | 1 5 | Thu Nov 23 00:00:00 2017 | 1 5 | Thu Nov 23 00:00:00 2017 | 1 5 | Thu Nov 23 00:00:00 2017 | 1 5 | Thu Nov 23 00:00:00 2017 | 1 5 | Thu Nov 23 00:00:00 2017 | 1 5 | Thu Nov 23 00:00:00 2017 | 1 5 | Thu Nov 23 00:00:00 2017 | 1 5 | Thu Nov 23 00:00:00 2017 | 1 5 | Thu Nov 23 00:00:00 2017 | 1 5 | Thu Nov 23 00:00:00 2017 | 1 5 | Thu Nov 23 00:00:00 2017 | 1 5 | Thu Nov 23 00:00:00 2017 | 1 6 | Wed Nov 22 00:00:00 2017 | 1 6 | Wed Nov 22 00:00:00 2017 | 1 6 | Thu Nov 23 00:00:00 2017 | 1 6 | Thu Nov 23 00:00:00 2017 | 1 6 | Thu Nov 23 00:00:00 2017 | 1 6 | Thu Nov 23 00:00:00 2017 | 1 6 | Thu Nov 23 00:00:00 2017 | 1 6 | Thu Nov 23 00:00:00 2017 | 1 6 | Thu Nov 23 00:00:00 2017 | 1 6 | Thu Nov 23 00:00:00 2017 | 1 (101 rows) SELECT * FROM ( SELECT user_id, COUNT(*) OVER (PARTITION BY sum(user_id), MIN(value_2)) FROM users_table GROUP BY user_id ) a ORDER BY 1 DESC, 2 DESC; user_id | count --------------------------------------------------------------------- 6 | 1 5 | 1 4 | 1 3 | 1 2 | 1 1 | 1 (6 rows) -- test with reference table partitioned on only a column from reference table SELECT * FROM ( SELECT DISTINCT user_id, it_name, count(id) OVER (PARTITION BY id) FROM users_table, users_ref_test_table ) a ORDER BY 1, 2, 3 LIMIT 20; user_id | it_name | count --------------------------------------------------------------------- 1 | User_1 | 101 1 | User_2 | 101 1 | User_3 | 101 1 | User_4 | 101 1 | User_5 | 101 1 | User_6 | 101 2 | User_1 | 101 2 | User_2 | 101 2 | User_3 | 101 2 | User_4 | 101 2 | User_5 | 101 2 | User_6 | 101 3 | User_1 | 101 3 | User_2 | 101 3 | User_3 | 101 3 | User_4 | 101 3 | User_5 | 101 3 | User_6 | 101 4 | User_1 | 101 4 | User_2 | 101 (20 rows) SELECT max(avg) FROM ( (SELECT avg(value_3) over (partition by user_id), user_id FROM events_table where event_type IN (1, 2)) UNION ALL (SELECT avg(value_3) over (partition by user_id), user_id FROM events_table where event_type IN (2, 3)) UNION ALL (SELECT avg(value_3) over (partition by user_id), user_id FROM events_table where event_type IN (3, 4)) UNION ALL (SELECT avg(value_3) over (partition by user_id), user_id FROM events_table where event_type IN (4, 5)) UNION ALL (SELECT avg(value_3) over (partition by user_id), user_id FROM events_table where event_type IN (5, 6)) UNION ALL (SELECT avg(value_3) over (partition by event_type), user_id FROM events_table where event_type IN (1, 6)) ) b GROUP BY user_id ORDER BY 1 DESC LIMIT 5; max --------------------------------------------------------------------- 5 3.09090909090909 3 3 2.875 (5 rows) SELECT * FROM ( ( SELECT user_id, sum(counter) FROM (SELECT user_id, sum(value_2) over (partition by user_id) AS counter FROM users_table UNION SELECT user_id, sum(value_2) over (partition by user_id) AS counter FROM events_table) user_id_1 GROUP BY user_id) UNION (SELECT user_id, sum(counter) FROM (SELECT user_id, sum(value_2) over (partition by user_id) AS counter FROM users_table UNION SELECT user_id, sum(value_2) over (partition by event_type) AS counter FROM events_table) user_id_2 GROUP BY user_id)) AS ftop ORDER BY 2 DESC, 1 DESC LIMIT 5; user_id | sum --------------------------------------------------------------------- 5 | 298 6 | 244 1 | 244 4 | 235 2 | 235 (5 rows) DROP VIEW subq;