Невозможно сбросить группы разделов (особенно оконные функции и PostgreSQL) - PullRequest
1 голос
/ 17 октября 2019

У меня есть простой набор данных, подобный этому:

SELECT UNNEST(ARRAY['A', 'A', 'A', 'B', 'B', 'A', 'C', 'B']) AS customer_name, generate_series(8, 1, -1) AS order_time;

+-------------+------------+
| customer_id | order_time |
+-------------+------------+
| "A"         | 8          |
+-------------+------------+
| "A"         | 7          |
+-------------+------------+
| "A"         | 6          |
+-------------+------------+
| "B"         | 5          |
+-------------+------------+
| "B"         | 4          |
+-------------+------------+
| "A"         | 3          |
+-------------+------------+
| "C"         | 2          |
+-------------+------------+
| "B"         | 1          |
+-------------+------------+

Я ищу одну строку:

+-------------+------------+
| customer_id | order_time |
+-------------+------------+
| "A"         | 6          |
+-------------+------------+

То есть я хочу получить первый order_timeиз последних (последовательных) customer_id. При использовании следующего SQL я всегда получаю «3» как order_time из customer_id A. Кажется, я не могу «сбросить» раздел.

SELECT customer_name, LAST_VALUE(order_time) OVER W
FROM
(
  SELECT UNNEST(ARRAY['A', 'A', 'A', 'B', 'B', 'A', 'C', 'B']) AS customer_name, generate_series(8, 1, -1) AS order_time
) X
WINDOW W AS (PARTITION BY customer_name ORDER BY order_time DESC ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING)
ORDER BY order_time DESC
LIMIT 1;

Использование PostgreSQL 11.5

1 Ответ

1 голос
/ 18 октября 2019

Вы можете использовать разницу между

ROW_NUMBER() OVER (ORDER BY order_time DESC) и

ROW_NUMBER() OVER (PARTITION BY customer_name ORDER BY order_time DESC), чтобы обеспечить группирование для структуры gaps-and-islands:

SELECT XX.customer_name, LAST_VALUE(order_time) OVER W FROM
(
 SELECT X.*, ROW_NUMBER() OVER (ORDER BY order_time DESC)-
             ROW_NUMBER() OVER (PARTITION BY customer_name ORDER BY order_time DESC) 
             AS rn

   FROM
   (
     SELECT UNNEST(ARRAY['A', 'A', 'A', 'B', 'B', 'A', 'C', 'B']) AS customer_name, 
            generate_series(8, 1, -1) AS order_time
    ) X
 ) XX
WINDOW W AS (PARTITION BY rn ORDER BY order_time DESC 
ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING)
LIMIT 1; 

Демо

...