1

我想创建一个窗口函数,该函数将计算当前行中字段的值出现在当前行之前的有序分区部分中的次数。为了使这个更具体,假设我们有一个像这样的表:

| 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。

4

1 回答 1

3

您可以在没有窗口函数的情况下使用self-left join和 a相当优雅地解决这个问题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用途。
于 2012-02-20T21:51:27.870 回答