我有一个订单表,其中有一列指示是买入还是卖出,行通常按时间戳排序。我想做的是对连续购买的群体进行操作,再加上他们的销售。例如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
,否则的NULL
。count()
返回一个从帧开始(在本例中是整个表)到当前行(最后一个同级)的运行计数。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演示两者。