PostgreSQL - GROUP 后续行
Posted
技术标签:
【中文标题】PostgreSQL - GROUP 后续行【英文标题】:PostgreSQL - GROUP subsequent rows 【发布时间】:2013-12-07 20:29:56 【问题描述】:我有一个表,其中包含一些按日期排序的记录。
我想获取每个后续组的开始和结束日期(按某些标准分组,例如位置)。
Example:
create table tbl (id int, date timestamp without time zone,
position int);
insert into tbl values
( 1 , '2013-12-01', 1),
( 2 , '2013-12-02', 2),
( 3 , '2013-12-03', 2),
( 4 , '2013-12-04', 2),
( 5 , '2013-12-05', 3),
( 6 , '2013-12-06', 3),
( 7 , '2013-12-07', 2),
( 8 , '2013-12-08', 2)
当然,如果我只是按位置分组,我会得到错误的结果,因为不同组的位置可能相同:
SELECT POSITION, min(date) MIN, max(date) MAX
FROM tbl GROUP BY POSITION
我会得到:
POSITION MIN MAX
1 December, 01 2013 00:00:00+0000 December, 01 2013 00:00:00+0000
3 December, 05 2013 00:00:00+0000 December, 06 2013 00:00:00+0000
2 December, 02 2013 00:00:00+0000 December, 08 2013 00:00:00+0000
但我想要:
POSITION MIN MAX
1 December, 01 2013 00:00:00+0000 December, 01 2013 00:00:00+0000
2 December, 02 2013 00:00:00+0000 December, 04 2013 00:00:00+0000
3 December, 05 2013 00:00:00+0000 December, 06 2013 00:00:00+0000
2 December, 07 2013 00:00:00+0000 December, 08 2013 00:00:00+0000
我找到了一个使用变量的solution for mysql,我可以移植它,但我相信 PostgreSQL 可以使用它的高级特性(如窗口函数)以更智能的方式完成它。
我使用的是 PostgreSQL 9.2
【问题讨论】:
【参考方案1】:可能有更优雅的解决方案,但试试这个:
WITH tmp_tbl AS (
SELECT *,
CASE WHEN lag(position,1) OVER(ORDER BY id)=position
THEN position
ELSE ROW_NUMBER() OVER(ORDER BY id)
END AS grouping_col
FROM tbl
)
, tmp_tbl2 AS(
SELECT position,date,
CASE WHEN lag(position,1)OVER(ORDER BY id)=position
THEN lag(grouping_col,1) OVER(ORDER BY id)
ELSE ROW_NUMBER() OVER(ORDER BY id)
END AS grouping_col
FROM tmp_tbl
)
SELECT POSITION, min(date) MIN, max(date) MAX
FROM tmp_tbl2 GROUP BY grouping_col,position
【讨论】:
【参考方案2】:*** 上有一些完整的答案,这里不再赘述,其原理是按照以下的区别对记录进行分组:
按日期排序时的行号(通过窗口函数) 日期与静态参考日期之间的差异。所以你有一个系列,例如:
rownum datediff diff
1 1 0 ^
2 2 0 | first group
3 3 0 v
4 5 1 ^
5 6 1 | second group
6 7 1 v
7 9 2 ^
8 10 2 v third group
【讨论】:
以上是关于PostgreSQL - GROUP 后续行的主要内容,如果未能解决你的问题,请参考以下文章
优化 PostgreSql 查询以获取找到的记录总数和基于多个 group by 的分页所需的有限行数
必须出现在 postgresql 的 GROUP BY 子句中