我需要查询帮助,让我们说这是表格中的数据。
timestamp
-------------------
2010-11-16 10:30:00
2010-11-16 10:37:00
2010-11-16 10:40:00
2010-11-16 10:45:00
2010-11-16 10:48:00
2010-11-16 10:55:00
2010-11-16 10:56:00
我希望每个第一行(时间戳)比最后一行至少晚5分钟。在这种情况下,查询应返回:
timestamp
-------------------
2010-11-16 10:30:00
2010-11-16 10:37:00
2010-11-16 10:45:00
2010-11-16 10:55:00
答案 0 :(得分:5)
由于每行依赖于前一行,因此很难用基于集合的方法解决。求助于recursive CTE(标准SQL):
WITH RECURSIVE cte AS (
(SELECT ts FROM tbl
ORDER BY ts
LIMIT 1)
UNION ALL
(SELECT t.ts
FROM cte c
JOIN tbl t ON t.ts >= c.ts + interval '5 min'
ORDER BY t.ts
LIMIT 1)
)
SELECT * FROM cte ORDER BY ts;
请注意我的初稿更新:
递归CTE中不允许聚合函数。我用ORDER BY
/ LIMIT 1
代替,当ts
上的索引支持时,它应该很快。
UNION
查询的每个分支周围的括号是允许LIMIT
所必需的,否则只有在UNION
查询结束时才允许这样做。
迭代遍历排序表的过程解决方案(带有plpgsql函数的示例)可能要快得多,因为它可以用单个表扫描来完成:
CREATE OR REPLACE FUNCTION f_rowgrid(i interval)
RETURNS SETOF timestamp AS
$func$
DECLARE
_this timestamp;
_last timestamp := '-infinity'; -- init so that 1 row passes
BEGIN
FOR _this IN
SELECT ts FROM tbl ORDER BY 1
LOOP
IF _this >= _last + i THEN
RETURN NEXT _this;
_last := _this;
END IF;
END LOOP;
END
$func$ LANGUAGE plpgsql;
呼叫:
SELECT * FROM f_rowgrid('5 min')
SQL Fiddle展示了两者。
对于这种类型的plpgsql函数,这是一个更复杂的例子:
可以轻松地使用动态SQL和EXECUTE
使其适用于任意表。