我有一些数据(按“TimeStamp”排序),如下所示:
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 | ... | ...
我需要为每条记录选择“TimeStamp”的下一个值(不仅仅是下一行)。
例如,上述数据如下所示:
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 | ... | ...
我一直在尝试使用窗口函数,但是我无法得到这个结果。有什么想法吗?
答案 0 :(得分:5)
甚至比dense_rank更酷,你可以使用lead
窗口函数:
SELECT Key, ts, lead(ts) OVER(ORDER BY ts ASC)
FROM tbl;
从欧文的回答中无耻地偷走sqlfiddle链接。
编辑:嗯,实际上它并不像你描述的那样完全,因为当两个值相等时它不会选择下一个更高的值。我不会删除答案,因为我认为它在这种情况下很有用,但我会将其标记为社区维基。
答案 1 :(得分:4)
这应该比相关子查询 更快
: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
dense_rank()
在CTE中获得无差距的排名。LEFT JOIN
将结果发送到DISTINCT
版本的偏移量为1
以获取“下一个”时间戳(并且只有一个)。GROUP BY 1,2
代替DISTINCT
y
。我希望DISTINCT
在这里更快,因为排序顺序与窗口函数的ORDER BY
一致。但请查看EXPLAIN ANALYZE
并自行查看。答案 2 :(得分:1)
您可以使用以下子选项获取“下一个”值:
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函数。