Подведение итогов «совпадений» с использованием оконной функции в SQL - PullRequest
1 голос
/ 21 февраля 2012

Я хочу создать оконную функцию, которая будет подсчитывать, сколько раз значение поля в текущей строке появляется в той части упорядоченного раздела, которая идет до текущей строки.Чтобы сделать это более конкретным, предположим, что у нас есть такая таблица:

| id| fruit  | date |
+---+--------+------+
| 1 | apple  |   1  |
| 1 | cherry |   2  |
| 1 | apple  |   3  |
| 1 | cherry |   4  |
| 2 | orange |   1  |
| 2 | grape  |   2  |
| 2 | grape  |   3  |

И мы хотим создать такую ​​таблицу (опуская столбец даты для ясности):

| id| fruit  | prior |  
+---+--------+-------+
| 1 | apple  |   0   |
| 1 | cherry |   0   |
| 1 | apple  |   1   |
| 1 | cherry |   1   |
| 2 | orange |   0   |
| 2 | grape  |   0   |
| 2 | grape  |   1   |

Обратите внимание, что для id = 1, перемещаясь по упорядоченному разделу, первая запись 'apple' ничего не соответствует (так как подразумеваемый набор пуст), следующий фрукт 'cherry' также не соответствует.Затем мы снова получаем «яблоко», которое совпадает и так далее.Я представляю, что SQL выглядит примерно так:

SELECT
id, fruit, 
<some kind of INTERSECT?> OVER (PARTITION BY id ORDER by date) AS prior
FROM fruit_table; 

Но я не могу найти ничего, что выглядит правильно.FWIW, я использую PostgreSQL 8.4.

1 Ответ

3 голосов
/ 21 февраля 2012

Вы можете решить эту проблему без оконной функции довольно элегантно с помощью само-левого соединения и count():

SELECT t.id, t.fruit, t.day, count(t0.*) AS prior
FROM   tbl t
LEFT   JOIN tbl t0 ON (t0.id, t0.fruit) = (t.id, t.fruit) AND t0.day < t.day
GROUP  BY t.id, t.day, t.fruit
ORDER  BY t.id, t.day

Если вы хотите сделать это с помощью оконной функции , эта функция должна работать:

SELECT id, fruit, day
      ,count(*) OVER (PARTITION BY id, fruit ORDER BY day) - 1 AS prior
FROM   tbl
ORDER  BY id, day

Если frame_end опущен, по умолчанию используется CURRENT ROW.

  • Вы фактически подсчитываете, сколько строк имели одинаковые (id, fruit) в предыдущие дни, включая текущую строку. Вот для чего - 1.
...