我有一张包含以下信息的表格:
CREATE TABLE TABLE1(
col1 bigint,
col2 TIMESTAMP,
col3 integer
)
一些示例数据是
28564635; "2014-03-11 07:02:16+03"; 51
28564635; "2014-03-11 07:06:25+03"; 52
28564635; "2014-03-11 07:13:38+03"; 53
28564635; "2014-03-11 07:21:19+03"; 56
28564636; "2014-03-11 07:01:16+03"; 31
28564636; "2014-03-11 07:06:16+03"; 29
28564636; "2014-03-11 07:37:16+03"; 30
28564636; "2014-03-11 07:39:16+03"; 31
值在 col1 和 col2 上按升序排序。现在的需求是根据条件在末尾追加一个计算列:
- 第一行的id为1
- 从第 2 行开始,如果当前 col1 = 前一行的 col1 和当前 col2 - 前一个 col2 < 30,则 ID 将为 1(与第 1 行相同),否则将 id 递增 1。
所以输出会是这样的
28564635; "2014-03-11 07:02:16+03"; 51; 1
28564635; "2014-03-11 07:06:25+03"; 52; 1
28564635; "2014-03-11 07:13:38+03"; 53; 1
28564635; "2014-03-11 07:21:19+03"; 56; 1
28564636; "2014-03-11 07:01:16+03"; 31; 2
28564636; "2014-03-11 07:06:16+03"; 29; 2
28564636; "2014-03-11 07:37:16+03"; 30; 3
28564636; "2014-03-11 07:39:16+03"; 31; 3
如何在不使用游标的情况下在 SQL 查询中实现这一点。
最佳答案
数据:
-- drop table if exists table1;
create table table1(
col1 bigint,
col2 timestamp,
col3 integer
);
insert into table1 (col1, col2, col3) values
(28564635, '2014-03-11 07:02:16+03', 51),
(28564635, '2014-03-11 07:06:25+03', 52),
(28564635, '2014-03-11 07:13:38+03', 53),
(28564635, '2014-03-11 07:21:19+03', 56),
(28564636, '2014-03-11 07:01:16+03', 31),
(28564636, '2014-03-11 07:06:16+03', 29),
(28564636, '2014-03-11 07:37:16+03', 30),
(28564636, '2014-03-11 07:39:16+03', 31)
;
查询:
select
*,
sum(test) over (order by col1, col2) as rn
from (
select
*,
(not
coalesce(extract(epoch from col2
- lag(col2) over(partition by col1 order by col2))/60.0 < 30, false)
)::int as test
from
table1
) a
结果:
28564635;2014-03-11 07:02:16;51;1;1
28564635;2014-03-11 07:06:25;52;0;1
28564635;2014-03-11 07:13:38;53;0;1
28564635;2014-03-11 07:21:19;56;0;1
28564636;2014-03-11 07:01:16;31;1;2
28564636;2014-03-11 07:06:16;29;0;2
28564636;2014-03-11 07:37:16;30;1;3
28564636;2014-03-11 07:39:16;31;0;3
解释:
- 获取当前
col1
的前一个col2
- 从之前的
col2
中减去当前的col2
并计算分钟数 - 测试是否少于 30 分钟
- 将结果合并为
false
(对于之前没有col2
的行) - 注意:前一个将标记每个第一行(按
col1
)和差异 > 30 分钟的每一行false
- 否定所有内容 - 对于我们想要增加计数器的所有行,我们得到
true
- 将 bool 值转换为整数(
true=1
,false=0
) - 在外部查询中计算我们测试的运行总和,按
col1
和col2
排序
关于sql - 根据 id 和时间戳差异创建唯一 id,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22372407/