我有一个订单表,其中有一列指示是买入还是卖出,行通常按时间戳排序。我想做的是对连续购买的群体进行操作,再加上他们的销售。例如B B S B S B B S -> (B B S) (B S) (B B S)
例子:

order_action |      timestamp
-------------+---------------------
buy          | 2013-10-03 13:03:02
buy          | 2013-10-08 13:03:02
sell         | 2013-10-10 15:58:02
buy          | 2013-11-01 09:30:02
buy          | 2013-11-01 14:03:02
sell         | 2013-11-07 10:34:02
buy          | 2013-12-03 15:46:02
sell         | 2013-12-09 16:00:03
buy          | 2013-12-11 13:02:02
sell         | 2013-12-18 15:59:03

最后,我将运行一个聚合函数(组是这样的,我可以根据其销售订单排除整个组),因此GROUP BY或分区窗口似乎是正确的方法,但我不知道如何获得这个特定的组。

最佳答案

使用count()作为窗口聚合函数,这可能非常简单:

SELECT *
      ,count(order_action = 'sell' OR NULL) OVER (ORDER BY ts DESC) AS grp
FROM   orders;

使用ts代替timestamp作为列名。避免reserved words作为标识符。
count()仅统计非空值。表达式order_action = 'sell' OR NULL导致'sell'的TRUE,否则的NULLcount()返回一个从帧开始(在本例中是整个表)到当前行(最后一个同级)的运行计数。sales的运行计数按请求对行进行分组。
我命令在OVER子句中降序,让每个组以后面的“sell”结束,而不是以前面的“sell”结束。这将导致组号降序。但这不重要,你只需要组号。
重复的时间戳是个问题(无论如何!).
升序组号的一种方法是:对窗口函数使用自定义the default frame definition
SELECT *
      ,count(order_action = 'sell' OR NULL)
       OVER (ORDER BY ts ROWS BETWEEN UNBOUNDED PRECEDING AND 1 PRECEDING) AS grp
FROM   orders;

FRAME definition演示两者。

09-26 17:29