我的postgreSQL 8.3.14数据库中有以下表格
timestamp status
2012-03-12 19:15:01 f
2012-03-12 19:15:02 f
2012-03-12 19:15:05 f
2012-03-12 19:17:01 t
-- END OF SLOT ONE (change from f to t)
2012-03-12 19:20:01 f
2012-03-12 19:25:01 f
2012-03-12 19:27:01 f
2012-03-12 20:15:01 t
-- END OF SLOT TWO (change from f to t)
不,我想得到以下结果:
因此,每次状态值从f变为t时,都会开始一个新的插槽。现在我想获得所有插槽和每个插槽的持续时间。时间戳不是每隔一分钟或每分钟左右,两个条目之间的差异或多或少是随机的。
我考虑过子查询和分组,但我不知道如何解决这个问题,至少是否有可能。所以我的问题是:这是可能的:-)如果是的话,如何开始?我因为f-t改变问题而陷入困境......
答案 0 :(得分:1)
如果你有一个现代版本的PG,你可以使用窗口函数做你想做的事情(在我的例子中,而不是时间戳,我有整数,但没关系): 我正在开发一个非窗口函数版本......
db=> select * from test1;
time | status
------+--------
1 | f
2 | f
3 | f
4 | t
5 | f
6 | f
7 | f
8 | t
9 | f
10 | t
(8 rows)
以下是带窗口函数的查询:
WITH a AS (
SELECT time,rank() OVER (ORDER BY time)
FROM (
SELECT status, time, lag(status,1) OVER (ORDER BY time) AS ls
FROM test1
) AS x
WHERE status AND NOT ls
-- select where the current status is true, the previous is false
), -- a is now the endings of the slots
b AS (
SELECT time, rank() OVER (ORDER BY time)
FROM (
SELECT status, time, LAG(status,1)
OVER (ORDER BY time) AS ls
FROM test1
) AS x
WHERE (NOT status AND ls) OR (NOT status AND ls IS NULL)
) -- b is now the beginning of the slots
SELECT b.time as time1, a.time as time2 FROM a,b WHERE a.rank=b.rank;
time1 | time2
------+------
1 | 4
5 | 8
9 | 10
以下是没有窗口函数的PG查询版本(实际上更短,但不太清晰)
SELECT min(time) as time1, time2 FROM
(
SELECT time, status,
(
SELECT time FROM test1 AS y
WHERE y.time >= x.time
ORDER BY (x.status = y.status)::int, y.time ASC LIMIT 1
) AS time2
FROM test1 AS x WHERE NOT status
) AS y GROUP BY y.time2 ORDER BY time2;