-- ===================================================================
-- 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
                     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
(62 rows)

-- lets have some queries that Citus shouldn't push 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;
ERROR:  could not run distributed query because the window function that is used cannot be pushed down
HINT:  Window functions are supported in two ways. Either add an equality filter on the distributed tables' partition column or use the window functions with a PARTITION BY clause containing the distribution column
-- user needs to supply partition by which should
-- include the distribution key
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;
ERROR:  could not run distributed query because the window function that is used cannot be pushed down
HINT:  Window functions are supported in two ways. Either add an equality filter on the distributed tables' partition column or use the window functions with a PARTITION BY clause containing the distribution column
-- user needs to supply partition by which should
-- include the distribution key
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;
ERROR:  could not run distributed query because the window function that is used cannot be pushed down
HINT:  Window functions are supported in two ways. Either add an equality filter on the distributed tables' partition column or use the window functions with a PARTITION BY clause containing the distribution column
-- w2 should not be pushed down
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;
ERROR:  could not run distributed query because the window function that is used cannot be pushed down
HINT:  Window functions are supported in two ways. Either add an equality filter on the distributed tables' partition column or use the window functions with a PARTITION BY clause containing the distribution column
-- w2 should not be pushed down
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;
ERROR:  could not run distributed query because the window function that is used cannot be pushed down
HINT:  Window functions are supported in two ways. Either add an equality filter on the distributed tables' partition column or use the window functions with a PARTITION BY clause containing the distribution column
-- GROUP BY includes the partition key, but not the WINDOW function
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;
ERROR:  could not run distributed query because the window function that is used cannot be pushed down
HINT:  Window functions are supported in two ways. Either add an equality filter on the distributed tables' partition column or use the window functions with a PARTITION BY clause containing the distribution column
-- GROUP BY includes the partition key, but not the WINDOW function
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;
ERROR:  could not run distributed query because the window function that is used cannot be pushed down
HINT:  Window functions are supported in two ways. Either add an equality filter on the distributed tables' partition column or use the window functions with a PARTITION BY clause containing the distribution column
-- Overriding window function but not supported
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;
ERROR:  could not run distributed query because the window function that is used cannot be pushed down
HINT:  Window functions are supported in two ways. Either add an equality filter on the distributed tables' partition column or use the window functions with a PARTITION BY clause containing the distribution column
-- Aggregate function on distribution column should error out
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;
ERROR:  could not run distributed query because the window function that is used cannot be pushed down
HINT:  Window functions are supported in two ways. Either add an equality filter on the distributed tables' partition column or use the window functions with a PARTITION BY clause containing the distribution column
-- 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;
ERROR:  could not run distributed query because the window function that is used cannot be pushed down
HINT:  Window functions are supported in two ways. Either add an equality filter on the distributed tables' partition column or use the window functions with a PARTITION BY clause containing the distribution column
-- UNION ALL with only one of them is not partitioned over distribution column which
-- should not be allowed.
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;
ERROR:  could not run distributed query because the window function that is used cannot be pushed down
HINT:  Window functions are supported in two ways. Either add an equality filter on the distributed tables' partition column or use the window functions with a PARTITION BY clause containing the distribution column
-- UNION with only one subquery which has a partition on non-distribution column should
-- error out
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;
ERROR:  could not run distributed query because the window function that is used cannot be pushed down
HINT:  Window functions are supported in two ways. Either add an equality filter on the distributed tables' partition column or use the window functions with a PARTITION BY clause containing the distribution column
DROP VIEW subq;
