sql - 根据 id 和时间戳差异创建唯一 id

标签 sql postgresql postgresql-9.1 postgresql-9.2

我有一张包含以下信息的表格:

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 查询中实现这一点。

最佳答案

SQLFiddle

数据:

-- 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

解释:

  1. 获取当前 col1 的前一个 col2
  2. 从之前的col2中减去当前的col2并计算分钟数
  3. 测试是否少于 30 分钟
  4. 将结果合并为 false(对于之前没有 col2 的行)
  5. 注意:前一个将标记每个第一行(按 col1)和差异 > 30 分钟的每一行 false
  6. 否定所有内容 - 对于我们想要增加计数器的所有行,我们得到 true
  7. 将 bool 值转换为整数(true=1false=0)
  8. 在外部查询中计算我们测试的运行总和,按 col1col2 排序

关于sql - 根据 id 和时间戳差异创建唯一 id,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22372407/

相关文章:

postgresql - 如何撤销对用户 postgres 的复制访问权限?

sql - HSQLDB中WHERE和ORDER BY的性能问题

sql - Mgmt Studio 将结果保存为问题

sql - 获取 SQL 中每周创建的记录数

postgresql - 使用 ASC 或 DESC 排序的主键?

postgresql - 在 PostgreSQL 子查询的 WHERE 子句中使用别名

ruby-on-rails - 如何在 ruby​​ on Rails 中查询 Postgresql HSTORE

postgresql,将列转换为没有rowid的标题

sql - 查询剩余余额

mysql - 单个查询中的多个 MySQL 计数