【发布时间】:2012-09-18 16:06:18
【问题描述】:
(PostgreSQL 8.4) 继续我的previous example,我希望进一步了解使用窗口函数处理间隙和孤岛。考虑下表和数据:
CREATE TABLE T1
(
id SERIAL PRIMARY KEY,
val INT, -- some device
status INT -- 0=OFF, 1=ON
);
INSERT INTO T1 (val, status) VALUES (10, 0);
INSERT INTO T1 (val, status) VALUES (11, 0);
INSERT INTO T1 (val, status) VALUES (11, 1);
INSERT INTO T1 (val, status) VALUES (10, 1);
INSERT INTO T1 (val, status) VALUES (11, 0);
INSERT INTO T1 (val, status) VALUES (10, 0);
如前所述,设备打开和关闭,这一次我希望提取一个特定的序列:
- 显示所有不重复的新
ON状态记录(同一设备连续两次) - 显示来自当前
ON设备的适当OFF状态
我能得到的最接近的是:
SELECT * FROM (
SELECT *
,lag(val, 1, 0) OVER (PARTITION BY status ORDER BY id) last_val
,lag(status, 1, -1) OVER (PARTITION BY val ORDER BY id) last_status
FROM t1
) x
WHERE (last_val <> val OR last_status <> status)
AND (status = 1 OR last_status <> -1)
ORDER BY id
这会过滤掉更多样本未包含的虚假数据,但本质上是关于取出后续重复项(无论状态如何)和不匹配的顶部 OFF 记录。返回记录3、4、5 和6,但我不想要第五个,它是一个OFF,它是在一个新的ON 之后出现的。所以我需要跳过这个差距,为当前活动的设备寻找下一个合适的OFF。
- 10 关闭——在这种情况下是假的,但会弄乱 lag()
- 11 关闭——在这种情况下是假的,但会弄乱 lag()
- 11 打开 -- 好的,新序列,包含在 SELECT 中
- 10 次开启 -- 好的,新序列,包含在 SELECT 中
- 11 关闭 -- 消息迟到,需要忽略间隙
- 10 关闭 -- 好的,正确关闭到第 4 行,需要包含在 SELECT 中
一旦正确过滤,我想在它上面使用lead() 来获取下一行的id(想象一个时间戳),并过滤掉所有不是ON 状态的记录。我想这将需要三个嵌入式 SELECT 语句。这将使我清楚地了解设备处于活动状态的时间,直到另一个ON 或正确转向OFF 的条件。
【问题讨论】:
标签: sql postgresql gaps-and-islands postgresql-8.4 window-functions