cod*_*tes 5 postgresql gaps-and-islands
我需要在查询中显示每行的连续赢/输,因此根据下表,查询应返回“预期”列。我尝试了一些窗口函数的方法,但没有成功。
create table matches (player text, dt date, is_winner boolean, expected integer )
insert into matches values
('A', '2019-01-01', TRUE, 0),
('A', '2019-01-03', TRUE, 1),
('A', '2019-01-04', TRUE, 2),
('A', '2019-01-09', FALSE, 0),
('A', '2019-01-10', FALSE, -1),
('A', '2019-01-15', TRUE, 0);
Run Code Online (Sandbox Code Playgroud)
create table matches (player text, dt date, is_winner boolean, expected integer )
insert into matches values
('A', '2019-01-01', TRUE, 0),
('A', '2019-01-03', TRUE, 1),
('A', '2019-01-04', TRUE, 2),
('A', '2019-01-09', FALSE, 0),
('A', '2019-01-10', FALSE, -1),
('A', '2019-01-15', TRUE, 0);
Run Code Online (Sandbox Code Playgroud)
逻辑是:
欢迎任何有关如何解决此问题的见解。我最后的手段是一个函数,每行都调用一个循环。
我已经使用 CTE 分阶段完成了这项工作,以便您可以在查询过程中看到它是如何完成的。每个 CTE 在输出中添加一列以显示进度。
老实说,这几乎是 CTE 名称的自我记录。
with lags as (
select player,
dt,
is_winner,
lag(is_winner) OVER (partition by player ORDER BY dt ASC) as prev_is_winner,
expected
from matches
),
group_changes as (
select lags.*,
case
when prev_is_winner <> is_winner or prev_is_winner is null
then 1
else 0
end as is_new_group
from lags
),
groups_numbered as (
select *,
sum(is_new_group)
over (partition by player order by dt, is_winner desc) as streak_group
from group_changes
),
expected_in_groups as (
select groups_numbered.*,
row_number()
over (partition by player,streak_group
order by dt asc, streak_group asc) - 1 as expected_unsigned
from groups_numbered
)
select expected_in_groups.*, case when is_winner = 't' then expected_unsigned else expected_unsigned * -1 end as actual
from expected_in_groups
order by player asc, dt asc;
Run Code Online (Sandbox Code Playgroud)
DB Fiddle Link(我添加了一个额外的行只是为了确保它在某个点工作)
基本上:
lags
CTE:用于LAG()
获取相对于当前行的前一个结果。group_changes
CTE:检测之前的连胜,无论输赢,是否已经结束groups_numbered
CTE:给每个连胜一个数字 expected_in_groups
CTE:对组中的行进行编号 select
:否定连败.
+--------+------------+-----------+----------------+----------+--------------+--------------+-------------------+--------+
| player | dt | is_winner | prev_is_winner | expected | is_new_group | streak_group | expected_unsigned | actual |
+--------+------------+-----------+----------------+----------+--------------+--------------+-------------------+--------+
| A | 2019-01-01 | t | | 0 | 1 | 1 | 0 | 0 |
| A | 2019-01-03 | t | t | 1 | 0 | 1 | 1 | 1 |
| A | 2019-01-04 | t | t | 2 | 0 | 1 | 2 | 2 |
| A | 2019-01-09 | f | t | 0 | 1 | 2 | 0 | 0 |
| A | 2019-01-10 | f | f | -1 | 0 | 2 | 1 | -1 |
| A | 2019-01-11 | f | f | -2 | 0 | 2 | 2 | -2 |
| A | 2019-01-15 | t | f | 0 | 1 | 3 | 0 | 0 |
+--------+------------+-----------+----------------+----------+--------------+--------------+-------------------+--------+
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
337 次 |
最近记录: |