[英]Running total of “matches” using a window function in SQL
我想創建一個窗口函數,該函數將計算當前行中字段的值出現在當前行之前的有序分區部分中的次數。 為了使這更具體,假設我們有一個這樣的表:
| 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'也不匹配。 然后我們再次進入'apple',這是匹配等等。 我在想象SQL看起來像這樣:
SELECT
id, fruit,
<some kind of INTERSECT?> OVER (PARTITION BY id ORDER by date) AS prior
FROM fruit_table;
但我找不到任何看起來正確的東西。 FWIW,我正在使用PostgreSQL 8.4。
您可以使用自左連接和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
我重命名了日期列day
因為date
是每個SQL標准和PostgreSQL中的保留字 。
我糾正了樣本數據中的錯誤。 他們有你的方式,它沒有檢查出來。 可能會讓人困惑。
如果您要使用window函數來執行此操作,則該方法應該可以工作:
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
的用途。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.