如何根据多列的排序对PostgreSQL中的聚合进行分组?

时间:2017-06-21 18:10:30

标签: postgresql postgis query-performance

给出一个表格'积分'像:

time  | session_id  | trail_id
------------------------------
  1   |      1      |    1
  2   |      1      |    1
  3   |      1      |    3
  4   |      1      |    3
  5   |      1      |    3
  6   |      1      |    1
  7   |      1      |    1
  8   |      1      |    1
  9   |      1      |    1
  10  |      1      |    1

如何对这些项目进行分组,以便我可以在' session_id'上使用聚合函数。关于trail_id,按时间排序? ie)我希望在trail_id随时间变化时拆分分组。

如下的查询:

SELECT count(session_id), session_id, trail_id
FROM <?>

会屈服:

count  | session_id  | trail_id
-------------------------------
   2   |     1       |    1
   3   |     1       |    3
   5   |     1       |    1

我相信这可以通过窗口功能完成,但到目前为止还没有成功。

以下并不是我需要的地方,因为无论时间如何,它都会对所有的trail_id进行分组:

SELECT session_id, trail_id, 
  first_value(time) OVER (PARTITION BY session_id, trail_id ORDER BY time) as v
FROM points

另外,在我的制作用例中,&#39;点&#39; table将是JOIN的结果,由几百万行组成。这些点将具有PostGIS几何类型,并与ST_MakeLine()函数聚合在一起。性能方面,在PL / pgSQL中尝试这会更好吗?

1 个答案:

答案 0 :(得分:3)

with points(time  , session_id  , trail_id) as(
    select 1   ,      1      ,    1 union all
    select  2   ,      1      ,    1 union all
    select  3   ,      1      ,    3 union all
    select  4   ,      1      ,    3 union all
    select  5   ,      1      ,    3 union all
    select  6   ,      1      ,    1 union all
    select  7   ,      1      ,    1 union all
    select  8   ,      1      ,    1 union all
    select  11   ,      1      ,    1 union all
    select  12  ,      1      ,    1  
)

select count(*), session_id, trail_id
from (
    select time, session_id, trail_id,
    row_number() over(order by time) -
    row_number() over(partition by session_id, trail_id order by time) as grp
    from points
)t
group by grp, session_id, trail_id
order by min(time)

嗯,这应该给你需要的结果,但是如果

  

'points'表将是JOIN的结果,由几百万行组成

然后可能表现不会那么可取。试试吧