Sql Postgres 9.1-获取下一个值
我有一些数据(按“时间戳”排序),如下所示:Sql Postgres 9.1-获取下一个值,sql,postgresql,window-functions,Sql,Postgresql,Window Functions,我有一些数据(按“时间戳”排序),如下所示: Key | TimeStamp | Column3 | ColumnN --------------+-------------------------+-------------+-------------- 1 | 2012-01-01 08:00:23 | ... | ... 2 | 2012-01-0
Key | TimeStamp | Column3 | ColumnN
--------------+-------------------------+-------------+--------------
1 | 2012-01-01 08:00:23 | ... | ...
2 | 2012-01-01 08:01:07 | ... | ...
3 | 2012-01-01 08:02:56 | ... | ...
6 | 2012-01-01 08:02:56 | ... | ...
4 | 2012-01-01 08:03:39 | ... | ...
5 | 2012-01-01 08:04:32 | ... | ...
Key | Begin | End | Column3 | ColumnN
--------------+-------------------------+-------------------------+-------------+--------------
1 | 2012-01-01 08:00:23 | 2012-01-01 08:01:07 | ... | ...
2 | 2012-01-01 08:01:07 | 2012-01-01 08:02:56 | ... | ...
3 | 2012-01-01 08:02:56 | 2012-01-01 08:03:39 | ... | ...
6 | 2012-01-01 08:02:56 | 2012-01-01 08:03:39 | ... | ...
4 | 2012-01-01 08:03:39 | 2012-01-01 08:04:32 | ... | ...
5 | 2012-01-01 08:04:32 | NULL | ... | ...
SELECT "Key",
t1.Timestamp as "Begin",
(SELECT min(t2."TimeStamp")
FROM the_table t2
WHERE t2."TimeStamp" > t1."TimeStamp") as "End",
column3, ...
FROM the_table t1
我需要为每条记录选择下一个值(不仅仅是下一行)
例如,上述数据如下所示:
Key | TimeStamp | Column3 | ColumnN
--------------+-------------------------+-------------+--------------
1 | 2012-01-01 08:00:23 | ... | ...
2 | 2012-01-01 08:01:07 | ... | ...
3 | 2012-01-01 08:02:56 | ... | ...
6 | 2012-01-01 08:02:56 | ... | ...
4 | 2012-01-01 08:03:39 | ... | ...
5 | 2012-01-01 08:04:32 | ... | ...
Key | Begin | End | Column3 | ColumnN
--------------+-------------------------+-------------------------+-------------+--------------
1 | 2012-01-01 08:00:23 | 2012-01-01 08:01:07 | ... | ...
2 | 2012-01-01 08:01:07 | 2012-01-01 08:02:56 | ... | ...
3 | 2012-01-01 08:02:56 | 2012-01-01 08:03:39 | ... | ...
6 | 2012-01-01 08:02:56 | 2012-01-01 08:03:39 | ... | ...
4 | 2012-01-01 08:03:39 | 2012-01-01 08:04:32 | ... | ...
5 | 2012-01-01 08:04:32 | NULL | ... | ...
SELECT "Key",
t1.Timestamp as "Begin",
(SELECT min(t2."TimeStamp")
FROM the_table t2
WHERE t2."TimeStamp" > t1."TimeStamp") as "End",
column3, ...
FROM the_table t1
我一直在尝试使用一个窗口函数来实现这一点,但我没有得到这个结果。有什么想法吗?您可以通过如下方式选择“下一步”值:
Key | TimeStamp | Column3 | ColumnN
--------------+-------------------------+-------------+--------------
1 | 2012-01-01 08:00:23 | ... | ...
2 | 2012-01-01 08:01:07 | ... | ...
3 | 2012-01-01 08:02:56 | ... | ...
6 | 2012-01-01 08:02:56 | ... | ...
4 | 2012-01-01 08:03:39 | ... | ...
5 | 2012-01-01 08:04:32 | ... | ...
Key | Begin | End | Column3 | ColumnN
--------------+-------------------------+-------------------------+-------------+--------------
1 | 2012-01-01 08:00:23 | 2012-01-01 08:01:07 | ... | ...
2 | 2012-01-01 08:01:07 | 2012-01-01 08:02:56 | ... | ...
3 | 2012-01-01 08:02:56 | 2012-01-01 08:03:39 | ... | ...
6 | 2012-01-01 08:02:56 | 2012-01-01 08:03:39 | ... | ...
4 | 2012-01-01 08:03:39 | 2012-01-01 08:04:32 | ... | ...
5 | 2012-01-01 08:04:32 | NULL | ... | ...
SELECT "Key",
t1.Timestamp as "Begin",
(SELECT min(t2."TimeStamp")
FROM the_table t2
WHERE t2."TimeStamp" > t1."TimeStamp") as "End",
column3, ...
FROM the_table t1
但这个查询可能很慢。如果需要快速,只需编写一个简单的PL/SQL函数。这应该比相关子查询快得多:
WITH x AS (
SELECT *, dense_rank() OVER (ORDER BY ts) AS rnk
FROM tbl
)
SELECT x.key, x.ts AS ts_begin, y.ts As ts_end
FROM x
LEFT JOIN (SELECT DISTINCT ts, rnk FROM x) y ON y.rnk = (x.rnk + 1)
ORDER BY x.ts
- 使用获得CTE中没有差距的排名
- 然后,
通过偏移量LEFT JOIN
将结果与自身的1
版本进行连接,以获得“下一个”时间戳(并且仅一个)DISTINCT
- 或者,对于
,您可以使用y
而不是groupby 1,2
。我希望这里的DISTINCT
速度更快,因为排序顺序与窗口函数的DISTINCT
一致。但是请检查orderby
解释分析
并亲自查看
SELECT Key, ts, lead(ts) OVER(ORDER BY ts ASC)
FROM tbl;
不知羞耻地从欧文的回答中盗取了链接
编辑:嗯,实际上它的工作原理与您描述的不完全相同,因为当两个值相等时,它不会选择下一个更高的值。我不会删除答案,因为我认为它在这种情况下很有用,但我会将其标记为社区维基。“我一直在尝试使用”-您应该向我们展示这些尝试。这也是我提出的解决方案之一,但(正如您指出的)它太慢了。您建议在函数中加入什么使其运行快速?此表有数亿条记录。@Losshorse只需编写一个函数,通过一个简单的光标从表中按时间顺序选择*(从旧到新)。对于游标
中的每一行,返回NEXT
之前存储在变量中的整行+end\u时间戳。