-- =================================================================== -- test top level window functions that are pushdownable -- =================================================================== -- a very simple window function with an aggregate and a window function -- distribution column is on the partition by clause SELECT user_id, COUNT(*) OVER (PARTITION BY user_id), rank() OVER (PARTITION BY user_id) FROM users_table ORDER BY 1 DESC, 2 DESC, 3 DESC LIMIT 5; user_id | count | rank --------------------------------------------------------------------- 6 | 10 | 1 6 | 10 | 1 6 | 10 | 1 6 | 10 | 1 6 | 10 | 1 (5 rows) -- a more complicated window clause, including an aggregate -- in both the window clause and the target entry SELECT user_id, avg(avg(value_3)) OVER (PARTITION BY user_id, MIN(value_2)) FROM users_table GROUP BY 1 ORDER BY 2 DESC NULLS LAST, 1 DESC; user_id | avg --------------------------------------------------------------------- 2 | 3 4 | 2.82608695652174 3 | 2.70588235294118 6 | 2.6 1 | 2.57142857142857 5 | 2.46153846153846 (6 rows) -- window clause operates on the results of a subquery SELECT user_id, max(value_1) OVER (PARTITION BY user_id, MIN(value_2)) FROM ( SELECT DISTINCT us.user_id, us.value_2, value_1, random() as r1 FROM users_table as us, events_table WHERE us.user_id = events_table.user_id AND event_type IN (1,2) ORDER BY user_id, value_2 ) s GROUP BY 1, value_1 ORDER BY 2 DESC, 1; user_id | max --------------------------------------------------------------------- 1 | 5 3 | 5 3 | 5 4 | 5 5 | 5 5 | 5 6 | 5 6 | 5 1 | 4 2 | 4 3 | 4 3 | 4 3 | 4 4 | 4 4 | 4 5 | 4 5 | 4 1 | 3 2 | 3 2 | 3 2 | 3 6 | 3 2 | 2 4 | 2 4 | 2 4 | 2 6 | 2 1 | 1 3 | 1 5 | 1 6 | 1 5 | 0 (32 rows) -- window function operates on the results of -- a join -- we also want to verify that this doesn't crash -- when the logging level is DEBUG4 SET log_min_messages TO DEBUG4; SELECT us.user_id, SUM(us.value_1) OVER (PARTITION BY us.user_id) FROM users_table us JOIN events_table ev ON (us.user_id = ev.user_id) GROUP BY 1, value_1 ORDER BY 1, 2 LIMIT 5; user_id | sum --------------------------------------------------------------------- 1 | 13 1 | 13 1 | 13 1 | 13 2 | 10 (5 rows) -- the same query, but this time join with an alias SELECT user_id, value_1, SUM(j.value_1) OVER (PARTITION BY j.user_id) FROM (users_table us JOIN events_table ev USING (user_id ) ) j GROUP BY user_id, value_1 ORDER BY 3 DESC, 2 DESC, 1 DESC LIMIT 5; user_id | value_1 | sum --------------------------------------------------------------------- 5 | 5 | 15 4 | 5 | 15 3 | 5 | 15 5 | 4 | 15 4 | 4 | 15 (5 rows) -- querying views that have window functions should be ok CREATE VIEW window_view 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; -- Window function in View works SELECT * FROM window_view 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) -- the other way around also should work fine -- query a view using window functions CREATE VIEW users_view AS SELECT * FROM users_table; SELECT DISTINCT user_id, rank() OVER (PARTITION BY user_id ORDER BY value_1) FROM users_view GROUP BY user_id, value_1 HAVING count(*) > 4 ORDER BY 2 DESC, 1; user_id | rank --------------------------------------------------------------------- 4 | 2 5 | 2 2 | 1 3 | 1 4 | 1 5 | 1 (6 rows) DROP VIEW users_view, window_view; -- window functions along with subquery in HAVING SELECT user_id, count (user_id) OVER (PARTITION BY user_id) FROM users_table GROUP BY user_id HAVING avg(value_1) < (SELECT min(k_no) FROM users_ref_test_table) ORDER BY 1 DESC,2 DESC LIMIT 1; user_id | count --------------------------------------------------------------------- 6 | 1 (1 row) -- window function uses columns from two different tables SELECT DISTINCT ON (events_table.user_id, rnk) events_table.user_id, rank() OVER my_win AS rnk FROM events_table, users_table WHERE users_table.user_id = events_table.user_id WINDOW my_win AS (PARTITION BY events_table.user_id, users_table.value_1 ORDER BY events_table.time DESC) ORDER BY rnk DESC, 1 DESC LIMIT 10; user_id | rnk --------------------------------------------------------------------- 3 | 121 5 | 118 2 | 116 3 | 115 4 | 113 2 | 111 5 | 109 3 | 109 4 | 106 2 | 106 (10 rows) -- the same query with reference table column is also on the partition by clause SELECT DISTINCT ON (events_table.user_id, rnk) events_table.user_id, rank() OVER my_win AS rnk FROM events_table, users_ref_test_table uref WHERE uref.id = events_table.user_id WINDOW my_win AS (PARTITION BY events_table.user_id, uref.k_no ORDER BY events_table.time DESC) ORDER BY rnk DESC, 1 DESC LIMIT 10; user_id | rnk --------------------------------------------------------------------- 2 | 24 2 | 23 2 | 22 3 | 21 2 | 21 3 | 20 2 | 20 3 | 19 2 | 19 3 | 18 (10 rows) -- similar query with no distribution column on the partition by clause SELECT DISTINCT ON (events_table.user_id, rnk) events_table.user_id, rank() OVER my_win AS rnk FROM events_table, users_ref_test_table uref WHERE uref.id = events_table.user_id WINDOW my_win AS (PARTITION BY events_table.value_2, uref.k_no ORDER BY events_table.time DESC) ORDER BY rnk DESC, 1 DESC LIMIT 10; user_id | rnk --------------------------------------------------------------------- 3 | 7 2 | 7 3 | 6 2 | 6 4 | 5 3 | 5 2 | 5 1 | 5 6 | 4 5 | 4 (10 rows) -- ORDER BY in the window function is an aggregate 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) ORDER BY 3 DESC, 2 DESC, 1 DESC; user_id | rnk | avg_val_2 --------------------------------------------------------------------- 1 | 1 | 3.3750000000000000 3 | 2 | 3.1666666666666667 5 | 1 | 2.6666666666666667 6 | 1 | 2.5000000000000000 4 | 1 | 2.5000000000000000 2 | 1 | 2.4736842105263158 4 | 2 | 2.4000000000000000 1 | 2 | 2.1428571428571429 5 | 2 | 2.0909090909090909 6 | 2 | 2.0000000000000000 2 | 2 | 2.0000000000000000 3 | 1 | 1.8000000000000000 (12 rows) -- lets push the limits of writing complex expressions aling with the window functions SELECT COUNT(*) OVER (PARTITION BY user_id, user_id + 1), rank() OVER (PARTITION BY user_id) as cnt1, COUNT(*) OVER (PARTITION BY user_id, abs(value_1 - value_2)) as cnt2, date_trunc('min', lag(time) OVER (PARTITION BY user_id ORDER BY time)) as datee, rank() OVER my_win as rnnk, avg(CASE WHEN user_id > 4 THEN value_1 ELSE value_2 END) FILTER (WHERE user_id > 2) OVER my_win_2 as filtered_count, sum(user_id * (5.0 / (value_1 + value_2 + 0.1)) * value_3) FILTER (WHERE value_1::text LIKE '%1%') OVER my_win_4 as cnt_with_filter_2 FROM users_table WINDOW my_win AS (PARTITION BY user_id, (value_1%3)::int ORDER BY time DESC), my_win_2 AS (PARTITION BY user_id, (value_1)::int ORDER BY time DESC), my_win_3 AS (PARTITION BY user_id, date_trunc('min', time)), my_win_4 AS (my_win_3 ORDER BY value_2, value_3) ORDER BY cnt_with_filter_2 DESC NULLS LAST, filtered_count DESC NULLS LAST, datee DESC NULLS LAST, rnnk DESC, cnt2 DESC, cnt1 DESC, user_id DESC LIMIT 5; count | cnt1 | cnt2 | datee | rnnk | filtered_count | cnt_with_filter_2 --------------------------------------------------------------------- 23 | 1 | 7 | Thu Nov 23 02:14:00 2017 | 6 | 0.00000000000000000000 | 72.7272727272727 10 | 1 | 3 | Wed Nov 22 23:01:00 2017 | 1 | 1.00000000000000000000 | 57.1428571428571 17 | 1 | 5 | Wed Nov 22 23:24:00 2017 | 8 | 3.0000000000000000 | 28.5714285714286 17 | 1 | 5 | | 10 | 2.6666666666666667 | 28.5714285714286 17 | 1 | 5 | Thu Nov 23 00:15:00 2017 | 7 | 3.6666666666666667 | 24.1935483870968 (5 rows) -- some tests with GROUP BY along with PARTITION BY SELECT user_id, rank() OVER my_win as my_rank, avg(avg(event_type)) OVER my_win_2 as avg, max(time) as mx_time FROM events_table GROUP BY user_id, value_2 WINDOW my_win AS (PARTITION BY user_id, max(event_type) ORDER BY count(*) DESC), my_win_2 AS (PARTITION BY user_id, avg(user_id) ORDER BY count(*) DESC) ORDER BY avg DESC, mx_time DESC, my_rank DESC, user_id DESC; user_id | my_rank | avg | mx_time --------------------------------------------------------------------- 6 | 1 | 3.0000000000000000 | Thu Nov 23 14:00:13.20013 2017 6 | 2 | 3.0000000000000000 | Thu Nov 23 11:16:13.106691 2017 6 | 1 | 3.0000000000000000 | Thu Nov 23 07:27:32.822068 2017 3 | 1 | 2.9857142857142857 | Thu Nov 23 16:31:56.219594 2017 4 | 2 | 2.9555555555555556 | Thu Nov 23 14:19:25.765876 2017 4 | 1 | 2.9555555555555556 | Thu Nov 23 08:36:53.871919 2017 1 | 4 | 2.8633333333333333 | Wed Nov 22 21:06:57.457147 2017 1 | 1 | 2.8250000000000000 | Thu Nov 23 21:54:46.924477 2017 2 | 2 | 2.7738095238095238 | Thu Nov 23 13:27:37.441959 2017 1 | 2 | 2.7722222222222222 | Thu Nov 23 09:23:30.994345 2017 3 | 1 | 2.7682539682539682 | Thu Nov 23 01:17:49.040685 2017 2 | 1 | 2.7142857142857143 | Thu Nov 23 15:58:49.273421 2017 1 | 3 | 2.5791666666666667 | Thu Nov 23 11:09:38.074595 2017 3 | 1 | 2.5714285714285714 | Thu Nov 23 16:44:41.903713 2017 2 | 1 | 2.5158730158730159 | Thu Nov 23 14:02:47.738901 2017 4 | 1 | 2.47777777777777778333 | Thu Nov 23 16:20:33.264457 2017 4 | 3 | 2.47777777777777778333 | Thu Nov 23 08:14:18.231273 2017 4 | 3 | 2.47777777777777778333 | Thu Nov 23 07:32:45.521278 2017 1 | 1 | 2.4000000000000000 | Thu Nov 23 10:23:27.617726 2017 2 | 1 | 2.3869047619047619 | Thu Nov 23 17:26:14.563216 2017 3 | 1 | 2.3841269841269841 | Thu Nov 23 18:08:26.550729 2017 3 | 1 | 2.3841269841269841 | Thu Nov 23 09:38:45.338008 2017 3 | 2 | 2.3841269841269841 | Thu Nov 23 06:44:50.887182 2017 2 | 2 | 2.3095238095238095 | Thu Nov 23 04:05:16.217731 2017 5 | 2 | 2.3000000000000000 | Thu Nov 23 14:28:51.833214 2017 5 | 2 | 2.3000000000000000 | Thu Nov 23 14:23:09.889786 2017 4 | 1 | 2.2000000000000000 | Thu Nov 23 18:10:21.338399 2017 2 | 1 | 2.09126984126984126667 | Thu Nov 23 03:35:04.321504 2017 5 | 1 | 2.0000000000000000 | Thu Nov 23 16:11:02.929469 2017 5 | 1 | 2.0000000000000000 | Thu Nov 23 14:40:40.467511 2017 5 | 1 | 2.0000000000000000 | Thu Nov 23 13:26:45.571108 2017 (31 rows) -- test for range and rows mode and different window functions -- mostly to make sure that deparsing works fine SELECT user_id, rank() OVER (PARTITION BY user_id ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW), dense_rank() OVER (PARTITION BY user_id RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW), CUME_DIST() OVER (PARTITION BY user_id RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING), PERCENT_RANK() OVER (PARTITION BY user_id ORDER BY avg(value_1) RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) FROM users_table GROUP BY 1 ORDER BY 4 DESC,3 DESC,2 DESC ,1 DESC; user_id | rank | dense_rank | cume_dist | percent_rank --------------------------------------------------------------------- 6 | 1 | 1 | 1 | 0 5 | 1 | 1 | 1 | 0 4 | 1 | 1 | 1 | 0 3 | 1 | 1 | 1 | 0 2 | 1 | 1 | 1 | 0 1 | 1 | 1 | 1 | 0 (6 rows) -- test exclude supported SELECT user_id, value_1, array_agg(value_1) OVER (PARTITION BY user_id ORDER BY value_1 RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW), array_agg(value_1) OVER (PARTITION BY user_id ORDER BY value_1 RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW EXCLUDE CURRENT ROW) FROM users_table WHERE user_id > 2 AND user_id < 6 ORDER BY user_id, value_1, 3, 4; user_id | value_1 | array_agg | array_agg --------------------------------------------------------------------- 3 | 0 | {0} | 3 | 1 | {0,1,1,1,1,1,1} | {0,1,1,1,1,1} 3 | 1 | {0,1,1,1,1,1,1} | {0,1,1,1,1,1} 3 | 1 | {0,1,1,1,1,1,1} | {0,1,1,1,1,1} 3 | 1 | {0,1,1,1,1,1,1} | {0,1,1,1,1,1} 3 | 1 | {0,1,1,1,1,1,1} | {0,1,1,1,1,1} 3 | 1 | {0,1,1,1,1,1,1} | {0,1,1,1,1,1} 3 | 2 | {0,1,1,1,1,1,1,2,2} | {0,1,1,1,1,1,1,2} 3 | 2 | {0,1,1,1,1,1,1,2,2} | {0,1,1,1,1,1,1,2} 3 | 3 | {0,1,1,1,1,1,1,2,2,3,3,3} | {0,1,1,1,1,1,1,2,2,3,3} 3 | 3 | {0,1,1,1,1,1,1,2,2,3,3,3} | {0,1,1,1,1,1,1,2,2,3,3} 3 | 3 | {0,1,1,1,1,1,1,2,2,3,3,3} | {0,1,1,1,1,1,1,2,2,3,3} 3 | 4 | {0,1,1,1,1,1,1,2,2,3,3,3,4,4,4,4} | {0,1,1,1,1,1,1,2,2,3,3,3,4,4,4} 3 | 4 | {0,1,1,1,1,1,1,2,2,3,3,3,4,4,4,4} | {0,1,1,1,1,1,1,2,2,3,3,3,4,4,4} 3 | 4 | {0,1,1,1,1,1,1,2,2,3,3,3,4,4,4,4} | {0,1,1,1,1,1,1,2,2,3,3,3,4,4,4} 3 | 4 | {0,1,1,1,1,1,1,2,2,3,3,3,4,4,4,4} | {0,1,1,1,1,1,1,2,2,3,3,3,4,4,4} 3 | 5 | {0,1,1,1,1,1,1,2,2,3,3,3,4,4,4,4,5} | {0,1,1,1,1,1,1,2,2,3,3,3,4,4,4,4} 4 | 0 | {0,0,0,0} | {0,0,0} 4 | 0 | {0,0,0,0} | {0,0,0} 4 | 0 | {0,0,0,0} | {0,0,0} 4 | 0 | {0,0,0,0} | {0,0,0} 4 | 1 | {0,0,0,0,1} | {0,0,0,0} 4 | 2 | {0,0,0,0,1,2,2,2} | {0,0,0,0,1,2,2} 4 | 2 | {0,0,0,0,1,2,2,2} | {0,0,0,0,1,2,2} 4 | 2 | {0,0,0,0,1,2,2,2} | {0,0,0,0,1,2,2} 4 | 3 | {0,0,0,0,1,2,2,2,3,3,3,3,3,3} | {0,0,0,0,1,2,2,2,3,3,3,3,3} 4 | 3 | {0,0,0,0,1,2,2,2,3,3,3,3,3,3} | {0,0,0,0,1,2,2,2,3,3,3,3,3} 4 | 3 | {0,0,0,0,1,2,2,2,3,3,3,3,3,3} | {0,0,0,0,1,2,2,2,3,3,3,3,3} 4 | 3 | {0,0,0,0,1,2,2,2,3,3,3,3,3,3} | {0,0,0,0,1,2,2,2,3,3,3,3,3} 4 | 3 | {0,0,0,0,1,2,2,2,3,3,3,3,3,3} | {0,0,0,0,1,2,2,2,3,3,3,3,3} 4 | 3 | {0,0,0,0,1,2,2,2,3,3,3,3,3,3} | {0,0,0,0,1,2,2,2,3,3,3,3,3} 4 | 4 | {0,0,0,0,1,2,2,2,3,3,3,3,3,3,4,4,4,4,4,4,4} | {0,0,0,0,1,2,2,2,3,3,3,3,3,3,4,4,4,4,4,4} 4 | 4 | {0,0,0,0,1,2,2,2,3,3,3,3,3,3,4,4,4,4,4,4,4} | {0,0,0,0,1,2,2,2,3,3,3,3,3,3,4,4,4,4,4,4} 4 | 4 | {0,0,0,0,1,2,2,2,3,3,3,3,3,3,4,4,4,4,4,4,4} | {0,0,0,0,1,2,2,2,3,3,3,3,3,3,4,4,4,4,4,4} 4 | 4 | {0,0,0,0,1,2,2,2,3,3,3,3,3,3,4,4,4,4,4,4,4} | {0,0,0,0,1,2,2,2,3,3,3,3,3,3,4,4,4,4,4,4} 4 | 4 | {0,0,0,0,1,2,2,2,3,3,3,3,3,3,4,4,4,4,4,4,4} | {0,0,0,0,1,2,2,2,3,3,3,3,3,3,4,4,4,4,4,4} 4 | 4 | {0,0,0,0,1,2,2,2,3,3,3,3,3,3,4,4,4,4,4,4,4} | {0,0,0,0,1,2,2,2,3,3,3,3,3,3,4,4,4,4,4,4} 4 | 4 | {0,0,0,0,1,2,2,2,3,3,3,3,3,3,4,4,4,4,4,4,4} | {0,0,0,0,1,2,2,2,3,3,3,3,3,3,4,4,4,4,4,4} 4 | 5 | {0,0,0,0,1,2,2,2,3,3,3,3,3,3,4,4,4,4,4,4,4,5,5} | {0,0,0,0,1,2,2,2,3,3,3,3,3,3,4,4,4,4,4,4,4,5} 4 | 5 | {0,0,0,0,1,2,2,2,3,3,3,3,3,3,4,4,4,4,4,4,4,5,5} | {0,0,0,0,1,2,2,2,3,3,3,3,3,3,4,4,4,4,4,4,4,5} 5 | 0 | {0,0} | {0} 5 | 0 | {0,0} | {0} 5 | 1 | {0,0,1,1,1} | {0,0,1,1} 5 | 1 | {0,0,1,1,1} | {0,0,1,1} 5 | 1 | {0,0,1,1,1} | {0,0,1,1} 5 | 2 | {0,0,1,1,1,2,2,2,2,2,2} | {0,0,1,1,1,2,2,2,2,2} 5 | 2 | {0,0,1,1,1,2,2,2,2,2,2} | {0,0,1,1,1,2,2,2,2,2} 5 | 2 | {0,0,1,1,1,2,2,2,2,2,2} | {0,0,1,1,1,2,2,2,2,2} 5 | 2 | {0,0,1,1,1,2,2,2,2,2,2} | {0,0,1,1,1,2,2,2,2,2} 5 | 2 | {0,0,1,1,1,2,2,2,2,2,2} | {0,0,1,1,1,2,2,2,2,2} 5 | 2 | {0,0,1,1,1,2,2,2,2,2,2} | {0,0,1,1,1,2,2,2,2,2} 5 | 3 | {0,0,1,1,1,2,2,2,2,2,2,3,3,3,3,3,3,3,3,3} | {0,0,1,1,1,2,2,2,2,2,2,3,3,3,3,3,3,3,3} 5 | 3 | {0,0,1,1,1,2,2,2,2,2,2,3,3,3,3,3,3,3,3,3} | {0,0,1,1,1,2,2,2,2,2,2,3,3,3,3,3,3,3,3} 5 | 3 | {0,0,1,1,1,2,2,2,2,2,2,3,3,3,3,3,3,3,3,3} | {0,0,1,1,1,2,2,2,2,2,2,3,3,3,3,3,3,3,3} 5 | 3 | {0,0,1,1,1,2,2,2,2,2,2,3,3,3,3,3,3,3,3,3} | {0,0,1,1,1,2,2,2,2,2,2,3,3,3,3,3,3,3,3} 5 | 3 | {0,0,1,1,1,2,2,2,2,2,2,3,3,3,3,3,3,3,3,3} | {0,0,1,1,1,2,2,2,2,2,2,3,3,3,3,3,3,3,3} 5 | 3 | {0,0,1,1,1,2,2,2,2,2,2,3,3,3,3,3,3,3,3,3} | {0,0,1,1,1,2,2,2,2,2,2,3,3,3,3,3,3,3,3} 5 | 3 | {0,0,1,1,1,2,2,2,2,2,2,3,3,3,3,3,3,3,3,3} | {0,0,1,1,1,2,2,2,2,2,2,3,3,3,3,3,3,3,3} 5 | 3 | {0,0,1,1,1,2,2,2,2,2,2,3,3,3,3,3,3,3,3,3} | {0,0,1,1,1,2,2,2,2,2,2,3,3,3,3,3,3,3,3} 5 | 3 | {0,0,1,1,1,2,2,2,2,2,2,3,3,3,3,3,3,3,3,3} | {0,0,1,1,1,2,2,2,2,2,2,3,3,3,3,3,3,3,3} 5 | 4 | {0,0,1,1,1,2,2,2,2,2,2,3,3,3,3,3,3,3,3,3,4,4,4} | {0,0,1,1,1,2,2,2,2,2,2,3,3,3,3,3,3,3,3,3,4,4} 5 | 4 | {0,0,1,1,1,2,2,2,2,2,2,3,3,3,3,3,3,3,3,3,4,4,4} | {0,0,1,1,1,2,2,2,2,2,2,3,3,3,3,3,3,3,3,3,4,4} 5 | 4 | {0,0,1,1,1,2,2,2,2,2,2,3,3,3,3,3,3,3,3,3,4,4,4} | {0,0,1,1,1,2,2,2,2,2,2,3,3,3,3,3,3,3,3,3,4,4} 5 | 5 | {0,0,1,1,1,2,2,2,2,2,2,3,3,3,3,3,3,3,3,3,4,4,4,5,5,5} | {0,0,1,1,1,2,2,2,2,2,2,3,3,3,3,3,3,3,3,3,4,4,4,5,5} 5 | 5 | {0,0,1,1,1,2,2,2,2,2,2,3,3,3,3,3,3,3,3,3,4,4,4,5,5,5} | {0,0,1,1,1,2,2,2,2,2,2,3,3,3,3,3,3,3,3,3,4,4,4,5,5} 5 | 5 | {0,0,1,1,1,2,2,2,2,2,2,3,3,3,3,3,3,3,3,3,4,4,4,5,5,5} | {0,0,1,1,1,2,2,2,2,2,2,3,3,3,3,3,3,3,3,3,4,4,4,5,5} (66 rows) -- test preceding and following on RANGE window SELECT user_id, value_1, array_agg(value_1) OVER range_window, array_agg(value_1) OVER range_window_exclude FROM users_table WHERE user_id > 2 AND user_id < 6 WINDOW range_window as (PARTITION BY user_id ORDER BY value_1 RANGE BETWEEN 1 PRECEDING AND 1 FOLLOWING), range_window_exclude as (PARTITION BY user_id ORDER BY value_1 RANGE BETWEEN 1 PRECEDING AND 1 FOLLOWING EXCLUDE CURRENT ROW) ORDER BY user_id, value_1, 3, 4; user_id | value_1 | array_agg | array_agg --------------------------------------------------------------------- 3 | 0 | {0,1,1,1,1,1,1} | {1,1,1,1,1,1} 3 | 1 | {0,1,1,1,1,1,1,2,2} | {0,1,1,1,1,1,2,2} 3 | 1 | {0,1,1,1,1,1,1,2,2} | {0,1,1,1,1,1,2,2} 3 | 1 | {0,1,1,1,1,1,1,2,2} | {0,1,1,1,1,1,2,2} 3 | 1 | {0,1,1,1,1,1,1,2,2} | {0,1,1,1,1,1,2,2} 3 | 1 | {0,1,1,1,1,1,1,2,2} | {0,1,1,1,1,1,2,2} 3 | 1 | {0,1,1,1,1,1,1,2,2} | {0,1,1,1,1,1,2,2} 3 | 2 | {1,1,1,1,1,1,2,2,3,3,3} | {1,1,1,1,1,1,2,3,3,3} 3 | 2 | {1,1,1,1,1,1,2,2,3,3,3} | {1,1,1,1,1,1,2,3,3,3} 3 | 3 | {2,2,3,3,3,4,4,4,4} | {2,2,3,3,4,4,4,4} 3 | 3 | {2,2,3,3,3,4,4,4,4} | {2,2,3,3,4,4,4,4} 3 | 3 | {2,2,3,3,3,4,4,4,4} | {2,2,3,3,4,4,4,4} 3 | 4 | {3,3,3,4,4,4,4,5} | {3,3,3,4,4,4,5} 3 | 4 | {3,3,3,4,4,4,4,5} | {3,3,3,4,4,4,5} 3 | 4 | {3,3,3,4,4,4,4,5} | {3,3,3,4,4,4,5} 3 | 4 | {3,3,3,4,4,4,4,5} | {3,3,3,4,4,4,5} 3 | 5 | {4,4,4,4,5} | {4,4,4,4} 4 | 0 | {0,0,0,0,1} | {0,0,0,1} 4 | 0 | {0,0,0,0,1} | {0,0,0,1} 4 | 0 | {0,0,0,0,1} | {0,0,0,1} 4 | 0 | {0,0,0,0,1} | {0,0,0,1} 4 | 1 | {0,0,0,0,1,2,2,2} | {0,0,0,0,2,2,2} 4 | 2 | {1,2,2,2,3,3,3,3,3,3} | {1,2,2,3,3,3,3,3,3} 4 | 2 | {1,2,2,2,3,3,3,3,3,3} | {1,2,2,3,3,3,3,3,3} 4 | 2 | {1,2,2,2,3,3,3,3,3,3} | {1,2,2,3,3,3,3,3,3} 4 | 3 | {2,2,2,3,3,3,3,3,3,4,4,4,4,4,4,4} | {2,2,2,3,3,3,3,3,4,4,4,4,4,4,4} 4 | 3 | {2,2,2,3,3,3,3,3,3,4,4,4,4,4,4,4} | {2,2,2,3,3,3,3,3,4,4,4,4,4,4,4} 4 | 3 | {2,2,2,3,3,3,3,3,3,4,4,4,4,4,4,4} | {2,2,2,3,3,3,3,3,4,4,4,4,4,4,4} 4 | 3 | {2,2,2,3,3,3,3,3,3,4,4,4,4,4,4,4} | {2,2,2,3,3,3,3,3,4,4,4,4,4,4,4} 4 | 3 | {2,2,2,3,3,3,3,3,3,4,4,4,4,4,4,4} | {2,2,2,3,3,3,3,3,4,4,4,4,4,4,4} 4 | 3 | {2,2,2,3,3,3,3,3,3,4,4,4,4,4,4,4} | {2,2,2,3,3,3,3,3,4,4,4,4,4,4,4} 4 | 4 | {3,3,3,3,3,3,4,4,4,4,4,4,4,5,5} | {3,3,3,3,3,3,4,4,4,4,4,4,5,5} 4 | 4 | {3,3,3,3,3,3,4,4,4,4,4,4,4,5,5} | {3,3,3,3,3,3,4,4,4,4,4,4,5,5} 4 | 4 | {3,3,3,3,3,3,4,4,4,4,4,4,4,5,5} | {3,3,3,3,3,3,4,4,4,4,4,4,5,5} 4 | 4 | {3,3,3,3,3,3,4,4,4,4,4,4,4,5,5} | {3,3,3,3,3,3,4,4,4,4,4,4,5,5} 4 | 4 | {3,3,3,3,3,3,4,4,4,4,4,4,4,5,5} | {3,3,3,3,3,3,4,4,4,4,4,4,5,5} 4 | 4 | {3,3,3,3,3,3,4,4,4,4,4,4,4,5,5} | {3,3,3,3,3,3,4,4,4,4,4,4,5,5} 4 | 4 | {3,3,3,3,3,3,4,4,4,4,4,4,4,5,5} | {3,3,3,3,3,3,4,4,4,4,4,4,5,5} 4 | 5 | {4,4,4,4,4,4,4,5,5} | {4,4,4,4,4,4,4,5} 4 | 5 | {4,4,4,4,4,4,4,5,5} | {4,4,4,4,4,4,4,5} 5 | 0 | {0,0,1,1,1} | {0,1,1,1} 5 | 0 | {0,0,1,1,1} | {0,1,1,1} 5 | 1 | {0,0,1,1,1,2,2,2,2,2,2} | {0,0,1,1,2,2,2,2,2,2} 5 | 1 | {0,0,1,1,1,2,2,2,2,2,2} | {0,0,1,1,2,2,2,2,2,2} 5 | 1 | {0,0,1,1,1,2,2,2,2,2,2} | {0,0,1,1,2,2,2,2,2,2} 5 | 2 | {1,1,1,2,2,2,2,2,2,3,3,3,3,3,3,3,3,3} | {1,1,1,2,2,2,2,2,3,3,3,3,3,3,3,3,3} 5 | 2 | {1,1,1,2,2,2,2,2,2,3,3,3,3,3,3,3,3,3} | {1,1,1,2,2,2,2,2,3,3,3,3,3,3,3,3,3} 5 | 2 | {1,1,1,2,2,2,2,2,2,3,3,3,3,3,3,3,3,3} | {1,1,1,2,2,2,2,2,3,3,3,3,3,3,3,3,3} 5 | 2 | {1,1,1,2,2,2,2,2,2,3,3,3,3,3,3,3,3,3} | {1,1,1,2,2,2,2,2,3,3,3,3,3,3,3,3,3} 5 | 2 | {1,1,1,2,2,2,2,2,2,3,3,3,3,3,3,3,3,3} | {1,1,1,2,2,2,2,2,3,3,3,3,3,3,3,3,3} 5 | 2 | {1,1,1,2,2,2,2,2,2,3,3,3,3,3,3,3,3,3} | {1,1,1,2,2,2,2,2,3,3,3,3,3,3,3,3,3} 5 | 3 | {2,2,2,2,2,2,3,3,3,3,3,3,3,3,3,4,4,4} | {2,2,2,2,2,2,3,3,3,3,3,3,3,3,4,4,4} 5 | 3 | {2,2,2,2,2,2,3,3,3,3,3,3,3,3,3,4,4,4} | {2,2,2,2,2,2,3,3,3,3,3,3,3,3,4,4,4} 5 | 3 | {2,2,2,2,2,2,3,3,3,3,3,3,3,3,3,4,4,4} | {2,2,2,2,2,2,3,3,3,3,3,3,3,3,4,4,4} 5 | 3 | {2,2,2,2,2,2,3,3,3,3,3,3,3,3,3,4,4,4} | {2,2,2,2,2,2,3,3,3,3,3,3,3,3,4,4,4} 5 | 3 | {2,2,2,2,2,2,3,3,3,3,3,3,3,3,3,4,4,4} | {2,2,2,2,2,2,3,3,3,3,3,3,3,3,4,4,4} 5 | 3 | {2,2,2,2,2,2,3,3,3,3,3,3,3,3,3,4,4,4} | {2,2,2,2,2,2,3,3,3,3,3,3,3,3,4,4,4} 5 | 3 | {2,2,2,2,2,2,3,3,3,3,3,3,3,3,3,4,4,4} | {2,2,2,2,2,2,3,3,3,3,3,3,3,3,4,4,4} 5 | 3 | {2,2,2,2,2,2,3,3,3,3,3,3,3,3,3,4,4,4} | {2,2,2,2,2,2,3,3,3,3,3,3,3,3,4,4,4} 5 | 3 | {2,2,2,2,2,2,3,3,3,3,3,3,3,3,3,4,4,4} | {2,2,2,2,2,2,3,3,3,3,3,3,3,3,4,4,4} 5 | 4 | {3,3,3,3,3,3,3,3,3,4,4,4,5,5,5} | {3,3,3,3,3,3,3,3,3,4,4,5,5,5} 5 | 4 | {3,3,3,3,3,3,3,3,3,4,4,4,5,5,5} | {3,3,3,3,3,3,3,3,3,4,4,5,5,5} 5 | 4 | {3,3,3,3,3,3,3,3,3,4,4,4,5,5,5} | {3,3,3,3,3,3,3,3,3,4,4,5,5,5} 5 | 5 | {4,4,4,5,5,5} | {4,4,4,5,5} 5 | 5 | {4,4,4,5,5,5} | {4,4,4,5,5} 5 | 5 | {4,4,4,5,5,5} | {4,4,4,5,5} (66 rows) -- test preceding and following on ROW window SELECT user_id, value_1, array_agg(value_1) OVER row_window, array_agg(value_1) OVER row_window_exclude FROM users_table WHERE user_id > 2 and user_id < 6 WINDOW row_window as (PARTITION BY user_id ORDER BY value_1 ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING), row_window_exclude as (PARTITION BY user_id ORDER BY value_1 ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING EXCLUDE CURRENT ROW) ORDER BY user_id, value_1, 3, 4; user_id | value_1 | array_agg | array_agg --------------------------------------------------------------------- 3 | 0 | {0,1} | {1} 3 | 1 | {0,1,1} | {0,1} 3 | 1 | {1,1,1} | {1,1} 3 | 1 | {1,1,1} | {1,1} 3 | 1 | {1,1,1} | {1,1} 3 | 1 | {1,1,1} | {1,1} 3 | 1 | {1,1,2} | {1,2} 3 | 2 | {1,2,2} | {1,2} 3 | 2 | {2,2,3} | {2,3} 3 | 3 | {2,3,3} | {2,3} 3 | 3 | {3,3,3} | {3,3} 3 | 3 | {3,3,4} | {3,4} 3 | 4 | {3,4,4} | {3,4} 3 | 4 | {4,4,4} | {4,4} 3 | 4 | {4,4,4} | {4,4} 3 | 4 | {4,4,5} | {4,5} 3 | 5 | {4,5} | {4} 4 | 0 | {0,0} | {0} 4 | 0 | {0,0,0} | {0,0} 4 | 0 | {0,0,0} | {0,0} 4 | 0 | {0,0,1} | {0,1} 4 | 1 | {0,1,2} | {0,2} 4 | 2 | {1,2,2} | {1,2} 4 | 2 | {2,2,2} | {2,2} 4 | 2 | {2,2,3} | {2,3} 4 | 3 | {2,3,3} | {2,3} 4 | 3 | {3,3,3} | {3,3} 4 | 3 | {3,3,3} | {3,3} 4 | 3 | {3,3,3} | {3,3} 4 | 3 | {3,3,3} | {3,3} 4 | 3 | {3,3,4} | {3,4} 4 | 4 | {3,4,4} | {3,4} 4 | 4 | {4,4,4} | {4,4} 4 | 4 | {4,4,4} | {4,4} 4 | 4 | {4,4,4} | {4,4} 4 | 4 | {4,4,4} | {4,4} 4 | 4 | {4,4,4} | {4,4} 4 | 4 | {4,4,5} | {4,5} 4 | 5 | {4,5,5} | {4,5} 4 | 5 | {5,5} | {5} 5 | 0 | {0,0} | {0} 5 | 0 | {0,0,1} | {0,1} 5 | 1 | {0,1,1} | {0,1} 5 | 1 | {1,1,1} | {1,1} 5 | 1 | {1,1,2} | {1,2} 5 | 2 | {1,2,2} | {1,2} 5 | 2 | {2,2,2} | {2,2} 5 | 2 | {2,2,2} | {2,2} 5 | 2 | {2,2,2} | {2,2} 5 | 2 | {2,2,2} | {2,2} 5 | 2 | {2,2,3} | {2,3} 5 | 3 | {2,3,3} | {2,3} 5 | 3 | {3,3,3} | {3,3} 5 | 3 | {3,3,3} | {3,3} 5 | 3 | {3,3,3} | {3,3} 5 | 3 | {3,3,3} | {3,3} 5 | 3 | {3,3,3} | {3,3} 5 | 3 | {3,3,3} | {3,3} 5 | 3 | {3,3,3} | {3,3} 5 | 3 | {3,3,4} | {3,4} 5 | 4 | {3,4,4} | {3,4} 5 | 4 | {4,4,4} | {4,4} 5 | 4 | {4,4,5} | {4,5} 5 | 5 | {4,5,5} | {4,5} 5 | 5 | {5,5} | {5} 5 | 5 | {5,5,5} | {5,5} (66 rows) -- repeat above 3 tests without grouping by distribution column SELECT value_2, rank() OVER (PARTITION BY value_2 ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW), dense_rank() OVER (PARTITION BY value_2 RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW), CUME_DIST() OVER (PARTITION BY value_2 RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING), PERCENT_RANK() OVER (PARTITION BY value_2 ORDER BY avg(value_1) RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) FROM users_table GROUP BY 1 ORDER BY 4 DESC,3 DESC,2 DESC ,1 DESC; value_2 | rank | dense_rank | cume_dist | percent_rank --------------------------------------------------------------------- 5 | 1 | 1 | 1 | 0 4 | 1 | 1 | 1 | 0 3 | 1 | 1 | 1 | 0 2 | 1 | 1 | 1 | 0 1 | 1 | 1 | 1 | 0 0 | 1 | 1 | 1 | 0 (6 rows) -- test exclude supported SELECT value_2, value_1, array_agg(value_1) OVER (PARTITION BY value_2 ORDER BY value_1 RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW), array_agg(value_1) OVER (PARTITION BY value_2 ORDER BY value_1 RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW EXCLUDE CURRENT ROW) FROM users_table WHERE value_2 > 2 AND value_2 < 6 ORDER BY value_2, value_1, 3, 4; value_2 | value_1 | array_agg | array_agg --------------------------------------------------------------------- 3 | 0 | {0,0,0} | {0,0} 3 | 0 | {0,0,0} | {0,0} 3 | 0 | {0,0,0} | {0,0} 3 | 1 | {0,0,0,1,1,1,1} | {0,0,0,1,1,1} 3 | 1 | {0,0,0,1,1,1,1} | {0,0,0,1,1,1} 3 | 1 | {0,0,0,1,1,1,1} | {0,0,0,1,1,1} 3 | 1 | {0,0,0,1,1,1,1} | {0,0,0,1,1,1} 3 | 2 | {0,0,0,1,1,1,1,2,2} | {0,0,0,1,1,1,1,2} 3 | 2 | {0,0,0,1,1,1,1,2,2} | {0,0,0,1,1,1,1,2} 3 | 3 | {0,0,0,1,1,1,1,2,2,3,3} | {0,0,0,1,1,1,1,2,2,3} 3 | 3 | {0,0,0,1,1,1,1,2,2,3,3} | {0,0,0,1,1,1,1,2,2,3} 3 | 4 | {0,0,0,1,1,1,1,2,2,3,3,4,4,4,4,4} | {0,0,0,1,1,1,1,2,2,3,3,4,4,4,4} 3 | 4 | {0,0,0,1,1,1,1,2,2,3,3,4,4,4,4,4} | {0,0,0,1,1,1,1,2,2,3,3,4,4,4,4} 3 | 4 | {0,0,0,1,1,1,1,2,2,3,3,4,4,4,4,4} | {0,0,0,1,1,1,1,2,2,3,3,4,4,4,4} 3 | 4 | {0,0,0,1,1,1,1,2,2,3,3,4,4,4,4,4} | {0,0,0,1,1,1,1,2,2,3,3,4,4,4,4} 3 | 4 | {0,0,0,1,1,1,1,2,2,3,3,4,4,4,4,4} | {0,0,0,1,1,1,1,2,2,3,3,4,4,4,4} 3 | 5 | {0,0,0,1,1,1,1,2,2,3,3,4,4,4,4,4,5} | {0,0,0,1,1,1,1,2,2,3,3,4,4,4,4,4} 4 | 0 | {0,0} | {0} 4 | 0 | {0,0} | {0} 4 | 1 | {0,0,1,1} | {0,0,1} 4 | 1 | {0,0,1,1} | {0,0,1} 4 | 2 | {0,0,1,1,2,2,2} | {0,0,1,1,2,2} 4 | 2 | {0,0,1,1,2,2,2} | {0,0,1,1,2,2} 4 | 2 | {0,0,1,1,2,2,2} | {0,0,1,1,2,2} 4 | 3 | {0,0,1,1,2,2,2,3,3,3,3,3,3,3} | {0,0,1,1,2,2,2,3,3,3,3,3,3} 4 | 3 | {0,0,1,1,2,2,2,3,3,3,3,3,3,3} | {0,0,1,1,2,2,2,3,3,3,3,3,3} 4 | 3 | {0,0,1,1,2,2,2,3,3,3,3,3,3,3} | {0,0,1,1,2,2,2,3,3,3,3,3,3} 4 | 3 | {0,0,1,1,2,2,2,3,3,3,3,3,3,3} | {0,0,1,1,2,2,2,3,3,3,3,3,3} 4 | 3 | {0,0,1,1,2,2,2,3,3,3,3,3,3,3} | {0,0,1,1,2,2,2,3,3,3,3,3,3} 4 | 3 | {0,0,1,1,2,2,2,3,3,3,3,3,3,3} | {0,0,1,1,2,2,2,3,3,3,3,3,3} 4 | 3 | {0,0,1,1,2,2,2,3,3,3,3,3,3,3} | {0,0,1,1,2,2,2,3,3,3,3,3,3} 4 | 4 | {0,0,1,1,2,2,2,3,3,3,3,3,3,3,4,4,4,4} | {0,0,1,1,2,2,2,3,3,3,3,3,3,3,4,4,4} 4 | 4 | {0,0,1,1,2,2,2,3,3,3,3,3,3,3,4,4,4,4} | {0,0,1,1,2,2,2,3,3,3,3,3,3,3,4,4,4} 4 | 4 | {0,0,1,1,2,2,2,3,3,3,3,3,3,3,4,4,4,4} | {0,0,1,1,2,2,2,3,3,3,3,3,3,3,4,4,4} 4 | 4 | {0,0,1,1,2,2,2,3,3,3,3,3,3,3,4,4,4,4} | {0,0,1,1,2,2,2,3,3,3,3,3,3,3,4,4,4} 4 | 5 | {0,0,1,1,2,2,2,3,3,3,3,3,3,3,4,4,4,4,5,5} | {0,0,1,1,2,2,2,3,3,3,3,3,3,3,4,4,4,4,5} 4 | 5 | {0,0,1,1,2,2,2,3,3,3,3,3,3,3,4,4,4,4,5,5} | {0,0,1,1,2,2,2,3,3,3,3,3,3,3,4,4,4,4,5} 5 | 0 | {0,0} | {0} 5 | 0 | {0,0} | {0} 5 | 1 | {0,0,1} | {0,0} 5 | 2 | {0,0,1,2,2} | {0,0,1,2} 5 | 2 | {0,0,1,2,2} | {0,0,1,2} 5 | 3 | {0,0,1,2,2,3,3,3,3} | {0,0,1,2,2,3,3,3} 5 | 3 | {0,0,1,2,2,3,3,3,3} | {0,0,1,2,2,3,3,3} 5 | 3 | {0,0,1,2,2,3,3,3,3} | {0,0,1,2,2,3,3,3} 5 | 3 | {0,0,1,2,2,3,3,3,3} | {0,0,1,2,2,3,3,3} 5 | 4 | {0,0,1,2,2,3,3,3,3,4,4} | {0,0,1,2,2,3,3,3,3,4} 5 | 4 | {0,0,1,2,2,3,3,3,3,4,4} | {0,0,1,2,2,3,3,3,3,4} 5 | 5 | {0,0,1,2,2,3,3,3,3,4,4,5,5} | {0,0,1,2,2,3,3,3,3,4,4,5} 5 | 5 | {0,0,1,2,2,3,3,3,3,4,4,5,5} | {0,0,1,2,2,3,3,3,3,4,4,5} (50 rows) -- test preceding and following on RANGE window SELECT value_2, value_1, array_agg(value_1) OVER range_window, array_agg(value_1) OVER range_window_exclude FROM users_table WHERE value_2 > 2 AND value_2 < 6 WINDOW range_window as (PARTITION BY value_2 ORDER BY value_1 RANGE BETWEEN 1 PRECEDING AND 1 FOLLOWING), range_window_exclude as (PARTITION BY value_2 ORDER BY value_1 RANGE BETWEEN 1 PRECEDING AND 1 FOLLOWING EXCLUDE CURRENT ROW) ORDER BY value_2, value_1, 3, 4; value_2 | value_1 | array_agg | array_agg --------------------------------------------------------------------- 3 | 0 | {0,0,0,1,1,1,1} | {0,0,1,1,1,1} 3 | 0 | {0,0,0,1,1,1,1} | {0,0,1,1,1,1} 3 | 0 | {0,0,0,1,1,1,1} | {0,0,1,1,1,1} 3 | 1 | {0,0,0,1,1,1,1,2,2} | {0,0,0,1,1,1,2,2} 3 | 1 | {0,0,0,1,1,1,1,2,2} | {0,0,0,1,1,1,2,2} 3 | 1 | {0,0,0,1,1,1,1,2,2} | {0,0,0,1,1,1,2,2} 3 | 1 | {0,0,0,1,1,1,1,2,2} | {0,0,0,1,1,1,2,2} 3 | 2 | {1,1,1,1,2,2,3,3} | {1,1,1,1,2,3,3} 3 | 2 | {1,1,1,1,2,2,3,3} | {1,1,1,1,2,3,3} 3 | 3 | {2,2,3,3,4,4,4,4,4} | {2,2,3,4,4,4,4,4} 3 | 3 | {2,2,3,3,4,4,4,4,4} | {2,2,3,4,4,4,4,4} 3 | 4 | {3,3,4,4,4,4,4,5} | {3,3,4,4,4,4,5} 3 | 4 | {3,3,4,4,4,4,4,5} | {3,3,4,4,4,4,5} 3 | 4 | {3,3,4,4,4,4,4,5} | {3,3,4,4,4,4,5} 3 | 4 | {3,3,4,4,4,4,4,5} | {3,3,4,4,4,4,5} 3 | 4 | {3,3,4,4,4,4,4,5} | {3,3,4,4,4,4,5} 3 | 5 | {4,4,4,4,4,5} | {4,4,4,4,4} 4 | 0 | {0,0,1,1} | {0,1,1} 4 | 0 | {0,0,1,1} | {0,1,1} 4 | 1 | {0,0,1,1,2,2,2} | {0,0,1,2,2,2} 4 | 1 | {0,0,1,1,2,2,2} | {0,0,1,2,2,2} 4 | 2 | {1,1,2,2,2,3,3,3,3,3,3,3} | {1,1,2,2,3,3,3,3,3,3,3} 4 | 2 | {1,1,2,2,2,3,3,3,3,3,3,3} | {1,1,2,2,3,3,3,3,3,3,3} 4 | 2 | {1,1,2,2,2,3,3,3,3,3,3,3} | {1,1,2,2,3,3,3,3,3,3,3} 4 | 3 | {2,2,2,3,3,3,3,3,3,3,4,4,4,4} | {2,2,2,3,3,3,3,3,3,4,4,4,4} 4 | 3 | {2,2,2,3,3,3,3,3,3,3,4,4,4,4} | {2,2,2,3,3,3,3,3,3,4,4,4,4} 4 | 3 | {2,2,2,3,3,3,3,3,3,3,4,4,4,4} | {2,2,2,3,3,3,3,3,3,4,4,4,4} 4 | 3 | {2,2,2,3,3,3,3,3,3,3,4,4,4,4} | {2,2,2,3,3,3,3,3,3,4,4,4,4} 4 | 3 | {2,2,2,3,3,3,3,3,3,3,4,4,4,4} | {2,2,2,3,3,3,3,3,3,4,4,4,4} 4 | 3 | {2,2,2,3,3,3,3,3,3,3,4,4,4,4} | {2,2,2,3,3,3,3,3,3,4,4,4,4} 4 | 3 | {2,2,2,3,3,3,3,3,3,3,4,4,4,4} | {2,2,2,3,3,3,3,3,3,4,4,4,4} 4 | 4 | {3,3,3,3,3,3,3,4,4,4,4,5,5} | {3,3,3,3,3,3,3,4,4,4,5,5} 4 | 4 | {3,3,3,3,3,3,3,4,4,4,4,5,5} | {3,3,3,3,3,3,3,4,4,4,5,5} 4 | 4 | {3,3,3,3,3,3,3,4,4,4,4,5,5} | {3,3,3,3,3,3,3,4,4,4,5,5} 4 | 4 | {3,3,3,3,3,3,3,4,4,4,4,5,5} | {3,3,3,3,3,3,3,4,4,4,5,5} 4 | 5 | {4,4,4,4,5,5} | {4,4,4,4,5} 4 | 5 | {4,4,4,4,5,5} | {4,4,4,4,5} 5 | 0 | {0,0,1} | {0,1} 5 | 0 | {0,0,1} | {0,1} 5 | 1 | {0,0,1,2,2} | {0,0,2,2} 5 | 2 | {1,2,2,3,3,3,3} | {1,2,3,3,3,3} 5 | 2 | {1,2,2,3,3,3,3} | {1,2,3,3,3,3} 5 | 3 | {2,2,3,3,3,3,4,4} | {2,2,3,3,3,4,4} 5 | 3 | {2,2,3,3,3,3,4,4} | {2,2,3,3,3,4,4} 5 | 3 | {2,2,3,3,3,3,4,4} | {2,2,3,3,3,4,4} 5 | 3 | {2,2,3,3,3,3,4,4} | {2,2,3,3,3,4,4} 5 | 4 | {3,3,3,3,4,4,5,5} | {3,3,3,3,4,5,5} 5 | 4 | {3,3,3,3,4,4,5,5} | {3,3,3,3,4,5,5} 5 | 5 | {4,4,5,5} | {4,4,5} 5 | 5 | {4,4,5,5} | {4,4,5} (50 rows) -- test preceding and following on ROW window SELECT value_2, value_1, array_agg(value_1) OVER row_window, array_agg(value_1) OVER row_window_exclude FROM users_table WHERE value_2 > 2 and value_2 < 6 WINDOW row_window as (PARTITION BY value_2 ORDER BY value_1 ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING), row_window_exclude as (PARTITION BY value_2 ORDER BY value_1 ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING EXCLUDE CURRENT ROW) ORDER BY value_2, value_1, 3, 4; value_2 | value_1 | array_agg | array_agg --------------------------------------------------------------------- 3 | 0 | {0,0} | {0} 3 | 0 | {0,0,0} | {0,0} 3 | 0 | {0,0,1} | {0,1} 3 | 1 | {0,1,1} | {0,1} 3 | 1 | {1,1,1} | {1,1} 3 | 1 | {1,1,1} | {1,1} 3 | 1 | {1,1,2} | {1,2} 3 | 2 | {1,2,2} | {1,2} 3 | 2 | {2,2,3} | {2,3} 3 | 3 | {2,3,3} | {2,3} 3 | 3 | {3,3,4} | {3,4} 3 | 4 | {3,4,4} | {3,4} 3 | 4 | {4,4,4} | {4,4} 3 | 4 | {4,4,4} | {4,4} 3 | 4 | {4,4,4} | {4,4} 3 | 4 | {4,4,5} | {4,5} 3 | 5 | {4,5} | {4} 4 | 0 | {0,0} | {0} 4 | 0 | {0,0,1} | {0,1} 4 | 1 | {0,1,1} | {0,1} 4 | 1 | {1,1,2} | {1,2} 4 | 2 | {1,2,2} | {1,2} 4 | 2 | {2,2,2} | {2,2} 4 | 2 | {2,2,3} | {2,3} 4 | 3 | {2,3,3} | {2,3} 4 | 3 | {3,3,3} | {3,3} 4 | 3 | {3,3,3} | {3,3} 4 | 3 | {3,3,3} | {3,3} 4 | 3 | {3,3,3} | {3,3} 4 | 3 | {3,3,3} | {3,3} 4 | 3 | {3,3,4} | {3,4} 4 | 4 | {3,4,4} | {3,4} 4 | 4 | {4,4,4} | {4,4} 4 | 4 | {4,4,4} | {4,4} 4 | 4 | {4,4,5} | {4,5} 4 | 5 | {4,5,5} | {4,5} 4 | 5 | {5,5} | {5} 5 | 0 | {0,0} | {0} 5 | 0 | {0,0,1} | {0,1} 5 | 1 | {0,1,2} | {0,2} 5 | 2 | {1,2,2} | {1,2} 5 | 2 | {2,2,3} | {2,3} 5 | 3 | {2,3,3} | {2,3} 5 | 3 | {3,3,3} | {3,3} 5 | 3 | {3,3,3} | {3,3} 5 | 3 | {3,3,4} | {3,4} 5 | 4 | {3,4,4} | {3,4} 5 | 4 | {4,4,5} | {4,5} 5 | 5 | {4,5,5} | {4,5} 5 | 5 | {5,5} | {5} (50 rows) -- some tests with GROUP BY, HAVING and LIMIT SELECT user_id, sum(event_type) OVER my_win , event_type FROM events_table GROUP BY user_id, event_type HAVING count(*) > 2 WINDOW my_win AS (PARTITION BY user_id, max(event_type) ORDER BY count(*) DESC) ORDER BY 2 DESC, 3 DESC, 1 DESC LIMIT 5; user_id | sum | event_type --------------------------------------------------------------------- 4 | 4 | 4 3 | 4 | 4 2 | 4 | 4 1 | 4 | 4 5 | 3 | 3 (5 rows) -- test PARTITION BY avg(...) ORDER BY avg(...) SELECT value_1, avg(value_3), dense_rank() OVER (PARTITION BY avg(value_3) ORDER BY avg(value_2)) FROM users_table GROUP BY 1 ORDER BY 1; value_1 | avg | dense_rank --------------------------------------------------------------------- 0 | 3.08333333333333 | 1 1 | 2.93333333333333 | 1 2 | 2.22222222222222 | 1 3 | 2.73076923076923 | 1 4 | 2.9047619047619 | 1 5 | 2.22222222222222 | 2 (6 rows) -- Group by has more columns than partition by SELECT DISTINCT user_id, SUM(value_2) OVER (PARTITION BY user_id) FROM users_table GROUP BY user_id, value_1, value_2 HAVING count(*) > 2 ORDER BY 2 DESC, 1 LIMIT 10; user_id | sum --------------------------------------------------------------------- 5 | 3 4 | 2 (2 rows) SELECT DISTINCT ON (user_id) user_id, SUM(value_2) OVER (PARTITION BY user_id) FROM users_table GROUP BY user_id, value_1, value_2 HAVING count(*) > 2 ORDER BY 1, 2 DESC LIMIT 10; user_id | sum --------------------------------------------------------------------- 4 | 2 5 | 3 (2 rows) SELECT DISTINCT ON (SUM(value_1) OVER (PARTITION BY user_id)) user_id, SUM(value_2) OVER (PARTITION BY user_id) FROM users_table GROUP BY user_id, value_1, value_2 HAVING count(*) > 2 ORDER BY (SUM(value_1) OVER (PARTITION BY user_id)) , 2 DESC, 1 LIMIT 10; user_id | sum --------------------------------------------------------------------- 5 | 3 4 | 2 (2 rows) -- not a meaningful query, with interesting syntax SELECT user_id, AVG(avg(value_1)) OVER (PARTITION BY user_id, max(user_id), MIN(value_2)), AVG(avg(user_id)) OVER (PARTITION BY user_id, min(user_id), AVG(value_1)) FROM users_table GROUP BY 1 ORDER BY 3 DESC, 2 DESC, 1 DESC; user_id | avg | avg --------------------------------------------------------------------- 6 | 2.1000000000000000 | 6.0000000000000000 5 | 2.6538461538461538 | 5.0000000000000000 4 | 2.7391304347826087 | 4.0000000000000000 3 | 2.3529411764705882 | 3.0000000000000000 2 | 2.3333333333333333 | 2.0000000000000000 1 | 3.2857142857142857 | 1.00000000000000000000 (6 rows) SELECT coordinator_plan($Q$ EXPLAIN (COSTS FALSE) SELECT user_id, AVG(avg(value_1)) OVER (PARTITION BY user_id, max(user_id), MIN(value_2)), AVG(avg(user_id)) OVER (PARTITION BY user_id, min(user_id), AVG(value_1)) FROM users_table GROUP BY 1 ORDER BY 3 DESC, 2 DESC, 1 DESC; $Q$); coordinator_plan --------------------------------------------------------------------- Sort Sort Key: remote_scan.avg_1 DESC, remote_scan.avg DESC, remote_scan.user_id DESC -> Custom Scan (Citus Adaptive) Task Count: 4 (4 rows) SELECT value_2, AVG(avg(value_1)) OVER (PARTITION BY value_2, max(value_2), MIN(value_2)), AVG(avg(value_2)) OVER (PARTITION BY value_2, min(value_2), AVG(value_1)) FROM users_table GROUP BY 1 ORDER BY 3 DESC, 2 DESC, 1 DESC; value_2 | avg | avg --------------------------------------------------------------------- 5 | 2.6923076923076923 | 5.0000000000000000 4 | 2.7500000000000000 | 4.0000000000000000 3 | 2.2941176470588235 | 3.0000000000000000 2 | 2.7619047619047619 | 2.0000000000000000 1 | 2.4285714285714286 | 1.00000000000000000000 0 | 2.2222222222222222 | 0.00000000000000000000 (6 rows) SELECT value_2, user_id, AVG(avg(value_1)) OVER (PARTITION BY value_2, max(value_2), MIN(value_2)), AVG(avg(value_2)) OVER (PARTITION BY user_id, min(value_2), AVG(value_1)) FROM users_table GROUP BY 1, 2 ORDER BY 3 DESC, 2 DESC, 1 DESC; value_2 | user_id | avg | avg --------------------------------------------------------------------- 5 | 5 | 2.6666666666666667 | 5.0000000000000000 5 | 4 | 2.6666666666666667 | 5.0000000000000000 5 | 3 | 2.6666666666666667 | 5.0000000000000000 5 | 2 | 2.6666666666666667 | 5.0000000000000000 2 | 6 | 2.54583333333333333333 | 2.0000000000000000 2 | 5 | 2.54583333333333333333 | 2.0000000000000000 2 | 4 | 2.54583333333333333333 | 2.0000000000000000 2 | 3 | 2.54583333333333333333 | 2.0000000000000000 2 | 2 | 2.54583333333333333333 | 2.0000000000000000 2 | 1 | 2.54583333333333333333 | 2.0000000000000000 0 | 6 | 2.50000000000000000000 | 0.00000000000000000000 0 | 5 | 2.50000000000000000000 | 0.00000000000000000000 0 | 4 | 2.50000000000000000000 | 0.00000000000000000000 0 | 2 | 2.50000000000000000000 | 0.00000000000000000000 0 | 1 | 2.50000000000000000000 | 0.00000000000000000000 4 | 6 | 2.45555555555555555000 | 4.0000000000000000 4 | 5 | 2.45555555555555555000 | 4.0000000000000000 4 | 4 | 2.45555555555555555000 | 4.0000000000000000 4 | 3 | 2.45555555555555555000 | 4.0000000000000000 4 | 2 | 2.45555555555555555000 | 4.0000000000000000 4 | 1 | 2.45555555555555555000 | 4.0000000000000000 3 | 6 | 2.3500000000000000 | 3.0000000000000000 3 | 5 | 2.3500000000000000 | 3.0000000000000000 3 | 4 | 2.3500000000000000 | 3.0000000000000000 3 | 3 | 2.3500000000000000 | 3.0000000000000000 3 | 2 | 2.3500000000000000 | 3.0000000000000000 3 | 1 | 2.3500000000000000 | 3.0000000000000000 1 | 6 | 1.90666666666666666000 | 1.00000000000000000000 1 | 5 | 1.90666666666666666000 | 1.00000000000000000000 1 | 4 | 1.90666666666666666000 | 1.00000000000000000000 1 | 3 | 1.90666666666666666000 | 1.00000000000000000000 1 | 2 | 1.90666666666666666000 | 1.00000000000000000000 (32 rows) SELECT user_id, sum(avg(user_id)) OVER () FROM users_table GROUP BY user_id ORDER BY 1 LIMIT 10; user_id | sum --------------------------------------------------------------------- 1 | 21.00000000000000000000 2 | 21.00000000000000000000 3 | 21.00000000000000000000 4 | 21.00000000000000000000 5 | 21.00000000000000000000 6 | 21.00000000000000000000 (6 rows) SELECT user_id, 1 + sum(value_1), 1 + AVG(value_2) OVER (partition by user_id) FROM users_table GROUP BY user_id, value_2 ORDER BY user_id, value_2; user_id | ?column? | ?column? --------------------------------------------------------------------- 1 | 5 | 3.2500000000000000 1 | 4 | 3.2500000000000000 1 | 6 | 3.2500000000000000 1 | 12 | 3.2500000000000000 2 | 3 | 3.5000000000000000 2 | 5 | 3.5000000000000000 2 | 13 | 3.5000000000000000 2 | 6 | 3.5000000000000000 2 | 17 | 3.5000000000000000 2 | 4 | 3.5000000000000000 3 | 3 | 4.0000000000000000 3 | 13 | 4.0000000000000000 3 | 10 | 4.0000000000000000 3 | 2 | 4.0000000000000000 3 | 17 | 4.0000000000000000 4 | 4 | 3.5000000000000000 4 | 28 | 3.5000000000000000 4 | 1 | 3.5000000000000000 4 | 11 | 3.5000000000000000 4 | 17 | 3.5000000000000000 4 | 8 | 3.5000000000000000 5 | 7 | 3.5000000000000000 5 | 17 | 3.5000000000000000 5 | 24 | 3.5000000000000000 5 | 9 | 3.5000000000000000 5 | 8 | 3.5000000000000000 5 | 10 | 3.5000000000000000 6 | 6 | 3.0000000000000000 6 | 3 | 3.0000000000000000 6 | 9 | 3.0000000000000000 6 | 3 | 3.0000000000000000 6 | 5 | 3.0000000000000000 (32 rows) SELECT user_id, 1 + sum(value_1), 1 + AVG(value_2) OVER (partition by user_id) FROM users_table GROUP BY user_id, value_2 ORDER BY 2 DESC, 1 LIMIT 5; user_id | ?column? | ?column? --------------------------------------------------------------------- 4 | 28 | 3.5000000000000000 5 | 24 | 3.5000000000000000 2 | 17 | 3.5000000000000000 3 | 17 | 4.0000000000000000 4 | 17 | 3.5000000000000000 (5 rows) -- rank and ordering in the reverse order SELECT user_id, avg(value_1), RANK() OVER (partition by user_id order by value_2) FROM users_table GROUP BY user_id, value_2 ORDER BY user_id, value_2 DESC; user_id | avg | rank --------------------------------------------------------------------- 1 | 3.6666666666666667 | 4 1 | 2.5000000000000000 | 3 1 | 3.0000000000000000 | 2 1 | 4.0000000000000000 | 1 2 | 1.5000000000000000 | 6 2 | 3.2000000000000000 | 5 2 | 1.6666666666666667 | 4 2 | 3.0000000000000000 | 3 2 | 1.3333333333333333 | 2 2 | 2.0000000000000000 | 1 3 | 2.6666666666666667 | 5 3 | 1.00000000000000000000 | 4 3 | 3.0000000000000000 | 3 3 | 2.4000000000000000 | 2 3 | 1.00000000000000000000 | 1 4 | 3.5000000000000000 | 6 4 | 3.2000000000000000 | 5 4 | 3.3333333333333333 | 4 4 | 0.00000000000000000000 | 3 4 | 3.0000000000000000 | 2 4 | 1.00000000000000000000 | 1 5 | 3.0000000000000000 | 6 5 | 2.3333333333333333 | 5 5 | 1.6000000000000000 | 4 5 | 2.8750000000000000 | 3 5 | 3.2000000000000000 | 2 5 | 3.0000000000000000 | 1 6 | 1.3333333333333333 | 5 6 | 2.0000000000000000 | 4 6 | 4.0000000000000000 | 3 6 | 1.00000000000000000000 | 2 6 | 2.5000000000000000 | 1 (32 rows) -- order by in the window function is same as avg(value_1) DESC SELECT user_id, avg(value_1), RANK() OVER (partition by user_id order by 1 / (1 + avg(value_1))) FROM users_table GROUP BY user_id, value_2 ORDER BY user_id, avg(value_1) DESC; user_id | avg | rank --------------------------------------------------------------------- 1 | 4.0000000000000000 | 1 1 | 3.6666666666666667 | 2 1 | 3.0000000000000000 | 3 1 | 2.5000000000000000 | 4 2 | 3.2000000000000000 | 1 2 | 3.0000000000000000 | 2 2 | 2.0000000000000000 | 3 2 | 1.6666666666666667 | 4 2 | 1.5000000000000000 | 5 2 | 1.3333333333333333 | 6 3 | 3.0000000000000000 | 1 3 | 2.6666666666666667 | 2 3 | 2.4000000000000000 | 3 3 | 1.00000000000000000000 | 4 3 | 1.00000000000000000000 | 4 4 | 3.5000000000000000 | 1 4 | 3.3333333333333333 | 2 4 | 3.2000000000000000 | 3 4 | 3.0000000000000000 | 4 4 | 1.00000000000000000000 | 5 4 | 0.00000000000000000000 | 6 5 | 3.2000000000000000 | 1 5 | 3.0000000000000000 | 2 5 | 3.0000000000000000 | 2 5 | 2.8750000000000000 | 4 5 | 2.3333333333333333 | 5 5 | 1.6000000000000000 | 6 6 | 4.0000000000000000 | 1 6 | 2.5000000000000000 | 2 6 | 2.0000000000000000 | 3 6 | 1.3333333333333333 | 4 6 | 1.00000000000000000000 | 5 (32 rows) EXPLAIN (COSTS FALSE) SELECT user_id, avg(value_1), RANK() OVER (partition by user_id order by 1 / (1 + avg(value_1))) FROM users_table GROUP BY user_id, value_2 ORDER BY user_id, avg(value_1) DESC; QUERY PLAN --------------------------------------------------------------------- Sort Sort Key: remote_scan.user_id, remote_scan.avg DESC -> Custom Scan (Citus Adaptive) Task Count: 4 Tasks Shown: One of 4 -> Task Node: host=localhost port=xxxxx dbname=regression -> WindowAgg -> Sort Sort Key: users_table.user_id, (('1'::numeric / ('1'::numeric + avg(users_table.value_1)))) -> HashAggregate Group Key: users_table.user_id, users_table.value_2 -> Seq Scan on users_table_1400256 users_table (13 rows) -- order by in the window function is same as avg(value_1) DESC SELECT user_id, avg(value_1), RANK() OVER (partition by user_id order by 1 / (1 + avg(value_1))) FROM users_table GROUP BY user_id, value_2 ORDER BY user_id, avg(value_1) DESC; user_id | avg | rank --------------------------------------------------------------------- 1 | 4.0000000000000000 | 1 1 | 3.6666666666666667 | 2 1 | 3.0000000000000000 | 3 1 | 2.5000000000000000 | 4 2 | 3.2000000000000000 | 1 2 | 3.0000000000000000 | 2 2 | 2.0000000000000000 | 3 2 | 1.6666666666666667 | 4 2 | 1.5000000000000000 | 5 2 | 1.3333333333333333 | 6 3 | 3.0000000000000000 | 1 3 | 2.6666666666666667 | 2 3 | 2.4000000000000000 | 3 3 | 1.00000000000000000000 | 4 3 | 1.00000000000000000000 | 4 4 | 3.5000000000000000 | 1 4 | 3.3333333333333333 | 2 4 | 3.2000000000000000 | 3 4 | 3.0000000000000000 | 4 4 | 1.00000000000000000000 | 5 4 | 0.00000000000000000000 | 6 5 | 3.2000000000000000 | 1 5 | 3.0000000000000000 | 2 5 | 3.0000000000000000 | 2 5 | 2.8750000000000000 | 4 5 | 2.3333333333333333 | 5 5 | 1.6000000000000000 | 6 6 | 4.0000000000000000 | 1 6 | 2.5000000000000000 | 2 6 | 2.0000000000000000 | 3 6 | 1.3333333333333333 | 4 6 | 1.00000000000000000000 | 5 (32 rows) -- limit is not pushed down to worker !! EXPLAIN (COSTS FALSE) SELECT user_id, avg(value_1), RANK() OVER (partition by user_id order by 1 / (1 + avg(value_1))) FROM users_table GROUP BY user_id, value_2 ORDER BY user_id, avg(value_1) DESC LIMIT 5; QUERY PLAN --------------------------------------------------------------------- Limit -> Sort Sort Key: remote_scan.user_id, remote_scan.avg DESC -> Custom Scan (Citus Adaptive) Task Count: 4 Tasks Shown: One of 4 -> Task Node: host=localhost port=xxxxx dbname=regression -> Limit -> Incremental Sort Sort Key: users_table.user_id, (avg(users_table.value_1)) DESC Presorted Key: users_table.user_id -> WindowAgg -> Sort Sort Key: users_table.user_id, (('1'::numeric / ('1'::numeric + avg(users_table.value_1)))) -> HashAggregate Group Key: users_table.user_id, users_table.value_2 -> Seq Scan on users_table_1400256 users_table (18 rows) EXPLAIN (COSTS FALSE) SELECT user_id, avg(value_1), RANK() OVER (partition by user_id order by 1 / (1 + avg(value_1))) FROM users_table GROUP BY user_id, value_2 ORDER BY user_id, avg(value_1) DESC LIMIT 5; QUERY PLAN --------------------------------------------------------------------- Limit -> Sort Sort Key: remote_scan.user_id, remote_scan.avg DESC -> Custom Scan (Citus Adaptive) Task Count: 4 Tasks Shown: One of 4 -> Task Node: host=localhost port=xxxxx dbname=regression -> Limit -> Incremental Sort Sort Key: users_table.user_id, (avg(users_table.value_1)) DESC Presorted Key: users_table.user_id -> WindowAgg -> Sort Sort Key: users_table.user_id, (('1'::numeric / ('1'::numeric + avg(users_table.value_1)))) -> HashAggregate Group Key: users_table.user_id, users_table.value_2 -> Seq Scan on users_table_1400256 users_table (18 rows) EXPLAIN (COSTS FALSE) SELECT user_id, avg(value_1), RANK() OVER (partition by user_id order by 1 / (1 + sum(value_2))) FROM users_table GROUP BY user_id, value_2 ORDER BY user_id, avg(value_1) DESC LIMIT 5; QUERY PLAN --------------------------------------------------------------------- Limit -> Sort Sort Key: remote_scan.user_id, remote_scan.avg DESC -> Custom Scan (Citus Adaptive) Task Count: 4 Tasks Shown: One of 4 -> Task Node: host=localhost port=xxxxx dbname=regression -> Limit -> Incremental Sort Sort Key: users_table.user_id, (avg(users_table.value_1)) DESC Presorted Key: users_table.user_id -> WindowAgg -> Sort Sort Key: users_table.user_id, ((1 / (1 + sum(users_table.value_2)))) -> HashAggregate Group Key: users_table.user_id, users_table.value_2 -> Seq Scan on users_table_1400256 users_table (18 rows) EXPLAIN (COSTS FALSE) SELECT user_id, avg(value_1), RANK() OVER (partition by user_id order by sum(value_2)) FROM users_table GROUP BY user_id, value_2 ORDER BY user_id, avg(value_1) DESC LIMIT 5; QUERY PLAN --------------------------------------------------------------------- Limit -> Sort Sort Key: remote_scan.user_id, remote_scan.avg DESC -> Custom Scan (Citus Adaptive) Task Count: 4 Tasks Shown: One of 4 -> Task Node: host=localhost port=xxxxx dbname=regression -> Limit -> Incremental Sort Sort Key: users_table.user_id, (avg(users_table.value_1)) DESC Presorted Key: users_table.user_id -> WindowAgg -> Sort Sort Key: users_table.user_id, (sum(users_table.value_2)) -> HashAggregate Group Key: users_table.user_id, users_table.value_2 -> Seq Scan on users_table_1400256 users_table (18 rows) -- Grouping can be pushed down with aggregates even when window function can't EXPLAIN (COSTS FALSE) SELECT user_id, count(value_1), stddev(value_1), count(user_id) OVER (PARTITION BY random()) FROM users_table GROUP BY user_id HAVING avg(value_1) > 2 LIMIT 1; QUERY PLAN --------------------------------------------------------------------- Limit -> WindowAgg -> Sort Sort Key: remote_scan.worker_column_5 -> Custom Scan (Citus Adaptive) Task Count: 4 Tasks Shown: One of 4 -> Task Node: host=localhost port=xxxxx dbname=regression -> HashAggregate Group Key: user_id Filter: (avg(value_1) > '2'::numeric) -> Seq Scan on users_table_1400256 users_table (13 rows) -- Window function with inlined CTE WITH cte as ( SELECT uref.id user_id, events_table.value_2, count(*) c FROM events_table JOIN users_ref_test_table uref ON uref.id = events_table.user_id GROUP BY 1, 2 ) SELECT DISTINCT cte.value_2, cte.c, sum(cte.value_2) OVER (PARTITION BY cte.c) FROM cte JOIN events_table et ON et.value_2 = cte.value_2 and et.value_2 = cte.c ORDER BY 1; value_2 | c | sum --------------------------------------------------------------------- 3 | 3 | 108 4 | 4 | 56 (2 rows) -- There was a strange bug where this wouldn't have window functions being pushed down -- Bug dependent on column ordering CREATE TABLE daily_uniques (value_2 float, user_id bigint); SELECT create_distributed_table('daily_uniques', 'user_id'); create_distributed_table --------------------------------------------------------------------- (1 row) EXPLAIN (COSTS FALSE) SELECT user_id, sum(value_2) AS commits, RANK () OVER ( PARTITION BY user_id ORDER BY sum(value_2) DESC ) FROM daily_uniques GROUP BY user_id HAVING sum(value_2) > 0 ORDER BY commits DESC LIMIT 10; QUERY PLAN --------------------------------------------------------------------- Limit -> Sort Sort Key: remote_scan.commits DESC -> Custom Scan (Citus Adaptive) Task Count: 4 Tasks Shown: One of 4 -> Task Node: host=localhost port=xxxxx dbname=regression -> Limit -> Sort Sort Key: (sum(daily_uniques.value_2)) DESC -> WindowAgg -> Sort Sort Key: daily_uniques.user_id, (sum(daily_uniques.value_2)) DESC -> HashAggregate Group Key: daily_uniques.user_id Filter: (sum(daily_uniques.value_2) > '0'::double precision) -> Seq Scan on daily_uniques_xxxxxxx daily_uniques (18 rows) DROP TABLE daily_uniques; -- Partition by reference table column joined to distribution column SELECT DISTINCT value_2, array_agg(rnk ORDER BY rnk) FROM ( SELECT events_table.value_2, sum(uref.k_no) OVER (PARTITION BY uref.id) AS rnk FROM events_table JOIN users_ref_test_table uref ON uref.id = events_table.user_id) sq GROUP BY 1 ORDER BY 1; value_2 | array_agg --------------------------------------------------------------------- 0 | {686,686,816,816,987,987,1104} 1 | {500,500,675,675,675,686,686,816,816,816,987,987,987,987,987,1104,1104,1104,1104,1104,1104,1104} 2 | {500,500,500,500,675,675,675,675,675,686,686,686,686,816,816,816,816,816,987,987,987,987,987,987,987,1104,1104,1104,1104,1104,1104} 3 | {500,500,500,500,675,686,686,686,816,816,987,987,987,1104,1104,1104,1104,1104} 4 | {675,675,675,675,686,686,686,816,816,816,987,987,1104,1104} 5 | {675,675,816,816,987,987,1104,1104,1104} (6 rows) -- https://github.com/citusdata/citus/issues/3754 select null = sum(null::int2) over () from public.users_table as ut limit 1; ?column? --------------------------------------------------------------------- (1 row) -- verify that this doesn't crash with DEBUG4 SET log_min_messages TO DEBUG4; SELECT user_id, max(value_1) OVER (PARTITION BY user_id, MIN(value_2)) FROM ( SELECT DISTINCT us.user_id, us.value_2, value_1, random() as r1 FROM users_table as us, events_table WHERE us.user_id = events_table.user_id AND event_type IN (1,2) ORDER BY user_id, value_2 ) s GROUP BY 1, value_1 ORDER BY 2 DESC, 1; user_id | max --------------------------------------------------------------------- 1 | 5 3 | 5 3 | 5 4 | 5 5 | 5 5 | 5 6 | 5 6 | 5 1 | 4 2 | 4 3 | 4 3 | 4 3 | 4 4 | 4 4 | 4 5 | 4 5 | 4 1 | 3 2 | 3 2 | 3 2 | 3 6 | 3 2 | 2 4 | 2 4 | 2 4 | 2 6 | 2 1 | 1 3 | 1 5 | 1 6 | 1 5 | 0 (32 rows)