我有一个包含2列的表:time
和id
。我们认为行首先按id排序,然后按时间排序。
╔════════╦══════════╗
║ time ║ id ║
╠════════╬══════════╣
║ 9:10 ║ 1 ║
║ 9:20 ║ 1 ║
║ 10:10 ║ 1 ║
║ 11:30 ║ 1 ║
║ 11:50 ║ 1 ║
║ 10:20 ║ 2 ║
║ 10:30 ║ 2 ║
║ 11:20 ║ 3 ║
║ 11:50 ║ 3 ║
╚════════╩══════════╝
我只想从中选择id
与“上一行”id
相同的行,并且与前一行的时差不到一小时。
这可以通过首先创建一个表来完成,其中第3列的时间差与前一行和第4列的id差异,并且只选择id_diff为0且time_diff在上面的行1小时。
但是这种方法似乎不够优雅,因为我想分别查看每个id
并在每个id
内查看其时间并检查连续差异是否超过一小时。这将更好地反映出分别查看每个id的逻辑,因为它们是不同的实体。
那么怎样才能对id进行分组,而不是两次使用窗口函数呢?我知道GROUP BY
的存在。
有效的代码,有两个窗口函数:
SELECT auxiliary_table_with_lag_diffs.*
FROM (
select info.*,
time-lag(time) over (Order by id, time ) as diff_time,
id-lag(id) over (order by id, time) as diff_id
from info
)auxiliary_table_with_lag_diffs
WHERE diff_time>'01:00:00'
AND diff_id=0
ORDER BY id, time;
答案 0 :(得分:1)
如果您想查看上一行,那么为什么要先按id
排序?
SELECT i.*
FROM (select i.*, lag(time) over (order by time) as prev_time,
lag(id) over (order by time) as prev_id
from info i
) i
WHERE time < prev_time + interval '1 hour' and id = prev_id
ORDER BY id, time;
如果您不想在输出中使用prev_time
和prev_id
,只需明确选择您想要的列。
注意:您可能需要>
而不是<
,具体取决于您的实际需求(问题含糊不清)。
答案 1 :(得分:1)
此处只需要一个分析函数调用:在同一ID中获取上一次。
SELECT *
FROM
(
select info.*,
time - lag(time) over (partition by id order by time) as diff_time
from info
) auxiliary_table_with_lag_diffs
WHERE diff_time > interval '1 hour';
ORDER BY id, time;