多次聚合多行

时间:2016-05-10 07:39:14

标签: sql postgresql aggregate

我有一组数据,其中包含type列和created_at时间列。我已经有了一个从数据库中提取相关数据的查询,这是返回的数据。

type            | created_at                   | row_num
-----------------------------------------------------
"ordersPage"    | "2015-07-21 11:32:40.568+12" | 1
"getQuote"      | "2015-07-21 15:49:47.072+12" | 2
"completeBrief" | "2015-07-23 01:00:15.341+12" | 3
"sendBrief"     | "2015-07-24 08:59:42.41+12"  | 4
"sendQuote"     | "2015-07-24 18:43:15.967+12" | 5
"acceptQuote"   | "2015-08-03 04:40:20.573+12" | 6

行号从postgres中的标准行号函数返回

ROW_NUMBER() OVER (ORDER BY created_at ASC) AS row_num

我想要做的是以某种方式聚合这些数据,以便在每个事件之间获得时间距离,因此输出数据可能看起来像这样

type_1          | type_2          | time_distance
--------------------------------------------------------
"ordersPage"    | "getQuote"      | 123423.3423
"getQuote"      | "completeBrief" | 123423.3423
"completeBrief" | "sendBrief"     | 123423.3423
"sendBrief"     | "sendQuote"     | 123423.3423
"sendQuote"     | "acceptQuote"   | 123423.3423

时间距离是一个以毫秒为单位的浮点数,在其他查询中,我一直在使用类似的东西来获得时差。

EXTRACT(EPOCH FROM (MAX(events.created_at) - MIN(events.created_at)))

但是这次我需要按行row_num的顺序排列每对事件,所以我需要(1,2), (2,3), (3,4)...的聚合

如果有可能,有什么想法吗?也不一定非精确,我可以处理重复项,并使用type_1type_2列以不同的顺序返回现有行。我只需要一种方法来至少获得上述值。

3 个答案:

答案 0 :(得分:1)

self join怎么样?它看起来像这样:

SELECT 
  t1.type
  , t2.type
  , ABS(t1.created_at - t2.created_at) AS time_diff
FROM your_table t1
INNER JOIN your_table t2
ON t1.row_num = t2.row_num + 1

答案 1 :(得分:1)

select type_1,
       type_2,
       created_at_2-created_at_1 as time_distance
from
(select 
type type_1,
lead(type,1) over (order by row_num) type_2,
created_at created_at_1,
lead(created_at,1) over (order by row_num) created_at_2
from table_name) temp
where type_2 is not null

答案 2 :(得分:1)

您可以使用LAG窗口功能将当前值与前一个值进行比较:

with
  t(type,created_at) as (
    values
      ('ordersPage', '2015-07-21 11:32:40.568+12'::timestamptz),
      ('getQuote', '2015-07-21 15:49:47.072+12'),
      ('completeBrief', '2015-07-23 01:00:15.341+12'),
      ('sendBrief', '2015-07-24 08:59:42.41+12'),
      ('sendQuote', '2015-07-24 18:43:15.967+12'),
      ('acceptQuote', '2015-08-03 04:40:20.573+12'))

select *, EXTRACT(EPOCH FROM created_at - lag(created_at) over (order by created_at))
from t
order by created_at