计算表中最大的负数系列
Posted
技术标签:
【中文标题】计算表中最大的负数系列【英文标题】:Count largest negative series in table 【发布时间】:2020-07-22 06:28:23 【问题描述】:我正在寻找一系列负数/正数。假设我有一个包含两列的表:order_time 和 win,其中 order_time 是日期,win 是 +1 或 -1。我想在“win”列中找到最大的负值系列。我知道如何在 Python 中做到这一点,但我想在 postgres 中做到这一点,而不是去其他环境。
例子
order_time wins
2020-01-02 17:12:19 0
2020-01-02 17:12:19 0
2020-01-02 21:02:15 1
2020-01-03 02:40:56 1
2020-01-03 10:38:39 0
2020-01-03 10:38:44 0
2020-01-03 10:38:44 1
2020-01-03 10:38:44 0
2020-01-03 10:58:32 1
2020-01-03 11:18:13 1
2020-01-03 11:18:35 1
输出
order_time wins s
2020-01-02 17:12:19 0 1
2020-01-02 17:12:19 0 2
2020-01-02 21:02:15 1 1
2020-01-03 02:40:56 1 2
2020-01-03 10:38:39 0 1
2020-01-03 10:38:44 0 2
2020-01-03 10:38:44 1 1
2020-01-03 10:38:44 0 1
2020-01-03 10:58:32 1 1
2020-01-03 11:18:13 1 2
2020-01-03 11:18:35 1 3
然后我会找到 s 列的最大值
【问题讨论】:
用你想要的输出提供样本数据 你的意思是连续的正数还是负数?日期重要不重要? 您的示例没有负数。您的意思是0
而不是 -1
?
尝试使用LAG- 函数写一些东西。
a_horse_with_no_name - 是的,您是对的,给您带来的不便,我们深表歉意。
【参考方案1】:
检测胜利何时更改,然后使用更改标志创建组。每组的行数,取最大行数。
with t (order_time, wins) as (values
(timestamp '2020-01-02 17:12:19', 0),
(timestamp '2020-01-02 17:12:19', 0),
(timestamp '2020-01-02 21:02:15', 1),
(timestamp '2020-01-03 02:40:56', 1),
(timestamp '2020-01-03 10:38:39', 0),
(timestamp '2020-01-03 10:38:44', 0),
(timestamp '2020-01-03 10:38:44', 1),
(timestamp '2020-01-03 10:38:44', 0),
(timestamp '2020-01-03 10:58:32', 1),
(timestamp '2020-01-03 11:18:13', 1),
(timestamp '2020-01-03 11:18:35', 1)
), ch as (
select t.*
, case coalesce(wins != lag(wins) over (order by order_time), true)
when true then 1
else 0
end as wins_changed
from t
), groups as (
select ch.*
, sum(wins_changed) over (order by order_time) as grp
from ch
), counts as (
select order_time
, wins
, row_number() over (partition by grp order by order_time) rn
from groups
)
select max(rn) from counts;
请注意,您的示例在第三行 2020-01-03 10:38:44
处不清楚。查询如何识别win=1
值是中间的值?出于这个原因,我的查询也为此行三元组返回 3。您可以通过更精确的order_time
(到毫秒)或添加另一个order by
标准来避免它。
Db 小提琴here.
【讨论】:
【参考方案2】:这是一个孤岛问题。识别相邻值的“孤岛”的最简单方法可能是行数差异法:
select t.*,
row_number() over (partition by wins, seqnum - seqnum_1 order by order_time) as s
from (select t.*,
row_number() over (order by order_time) as seqnum,
row_number() over (partition by wins order by order_time) as seqnum_1
from t
) t;
您实际上可以在没有子查询的情况下获得最长的连胜:
select count(*) over (partition by wins, seqnum - seqnum_1 order by order_time) as s
from (select t.*,
row_number() over (order by order_time) as seqnum,
row_number() over (partition by wins order by order_time) as seqnum_1
from t
) t
order by s desc
limit 1;
如果您想要最长的输(或赢)系列,只需将where wins = <whatever>
添加到外部查询。
Here 是一个 dbfiddle。
【讨论】:
以上是关于计算表中最大的负数系列的主要内容,如果未能解决你的问题,请参考以下文章