在有序数据集中指定多组连续相等的值
Designate groups of consecutive equal values in an ordered dataset
我正在尝试使输出如下所示。问题是我无法执行 first_value 或 RANK,因为当我按事件分区并按时间排序时,它不会按该顺序分解它们。我需要他们先按时间排序,然后每次分区。
已知解决方案之一
使用lag()
标记行当event
变化和累积sum()
指定组,例如:
with my_table(event, time) as (
values
('A', '12:01'),
('A', '12:02'),
('B', '12:03'),
('A', '12:04'),
('A', '12:05'),
('B', '12:06'),
('B', '12:07'),
('A', '12:08')
)
select
event,
time,
sum(change) over (order by time) as "desired row number"
from (
select
event,
time,
(event is distinct from lag(event) over (order by time))::int as change
from my_table
) s
event | time | desired row number
-------+-------+--------------------
A | 12:01 | 1
A | 12:02 | 1
B | 12:03 | 2
A | 12:04 | 3
A | 12:05 | 3
B | 12:06 | 4
B | 12:07 | 4
A | 12:08 | 5
(8 rows)
自定义聚合
如果有这个功能就好了:
select *, group_number(event) over (order by time)
from my_table;
这可以通过自定义聚合来完成:
create type group_number_internal as (number int, lag text);
create or replace function group_number_transition(group_number_internal, anyelement)
returns group_number_internal language sql strict as $$
select
case
when ::text is distinct from .lag then .number+ 1
else .number
end,
::text
$$;
create or replace function group_number_final(group_number_internal)
returns int language sql as $$
select .number
$$;
create aggregate group_number(anyelement) (
sfunc = group_number_transition,
stype = group_number_internal,
finalfunc = group_number_final,
initcond = '(0, null)'
);
我正在尝试使输出如下所示。问题是我无法执行 first_value 或 RANK,因为当我按事件分区并按时间排序时,它不会按该顺序分解它们。我需要他们先按时间排序,然后每次分区。
已知解决方案之一
使用lag()
标记行当event
变化和累积sum()
指定组,例如:
with my_table(event, time) as (
values
('A', '12:01'),
('A', '12:02'),
('B', '12:03'),
('A', '12:04'),
('A', '12:05'),
('B', '12:06'),
('B', '12:07'),
('A', '12:08')
)
select
event,
time,
sum(change) over (order by time) as "desired row number"
from (
select
event,
time,
(event is distinct from lag(event) over (order by time))::int as change
from my_table
) s
event | time | desired row number
-------+-------+--------------------
A | 12:01 | 1
A | 12:02 | 1
B | 12:03 | 2
A | 12:04 | 3
A | 12:05 | 3
B | 12:06 | 4
B | 12:07 | 4
A | 12:08 | 5
(8 rows)
自定义聚合
如果有这个功能就好了:
select *, group_number(event) over (order by time)
from my_table;
这可以通过自定义聚合来完成:
create type group_number_internal as (number int, lag text);
create or replace function group_number_transition(group_number_internal, anyelement)
returns group_number_internal language sql strict as $$
select
case
when ::text is distinct from .lag then .number+ 1
else .number
end,
::text
$$;
create or replace function group_number_final(group_number_internal)
returns int language sql as $$
select .number
$$;
create aggregate group_number(anyelement) (
sfunc = group_number_transition,
stype = group_number_internal,
finalfunc = group_number_final,
initcond = '(0, null)'
);