无法整理查询以提取给定时间戳的聚合值以及之前的时间戳。给出以下架构:
name TEXT,
ts TIMESTAMP,
X NUMERIC,
Y NUMERIC
由于数据缺口,ts
列中存在空白,我正在尝试构建一个查询来生成
name,
date_trunc('day' q1.ts),
avg(q1.X),
sum(q2.Y),
date_trunc('day', q2.ts),
avg(q2.X),
sum(q2.Y)
上半场很简单:
SELECT q1.name, date_trunc('day', q1.ts), avg(q1.X), sum(q1.Y)
FROM data as q1
GROUP BY 1, 2
ORDER BY 1, 2;
但不确定如何生成关系以找到每行之前的“日”。我正在尝试这样的内部联接:
SELECT q1.name, q1.day, q1.avg, q1.sum, q2.day, q2.avg, q2.sum
FROM (
SELECT name, date_trunc('day', ts) AS day, avg(X) AS avg, sum(Y) as sum
FROM data
GROUP BY 1,2
ORDER BY 1,2
) q1 INNER JOIN (
SELECT name, date_trunc('day', ts) AS day, avg(X) AS avg, sum(Y) as sum
FROM data
GROUP BY 1,2
ORDER BY 1,2
) q2 ON (
q1.name = q2.name
AND q2.day = q1.day - interval '1 day'
);
问题在于,它不包括下一个“日”在当天之前超过1天的情况。
答案 0 :(得分:2)
这里的特殊困难是您需要在聚合行后数天。您可以使用窗口函数row_number()
在单个查询级别执行此操作,因为窗口函数在GROUP BY
聚合之后应用。
另外,使用CTE避免多次执行相同的子查询:
WITH q AS (
SELECT name, ts::date AS day
,avg(x) AS avg_x, sum(y) AS sum_y
,row_number() OVER (PARTITION BY name ORDER BY ts::date) AS rn
FROM data
GROUP BY 1,2
)
SELECT q1.name, q1.day, q1.avg_x, q1.sum_y
,q2.day AS day2, q2.avg_x AS avg_x2, q2.sum_y AS sum_y2
FROM q q1
LEFT JOIN q q2 ON q1.name = q2.name
AND q1.rn = q2.rn + 1
ORDER BY 1,2;
使用更简单的演员陈述(ts::date
)代替date_trunc('day', ts)
来获得“天”。
LEFT [OUTER] JOIN
(与[INNER] JOIN
相对)有助于保留第一行的角落情况,前一天没有。
ORDER BY
应该应用于外部查询。
答案 1 :(得分:1)
问题不是很清楚,但听起来你实际上是在试图填补空白,同时跟踪领先/滞后的行。
要填补空白,请查看generate_series()
,然后将其与表格一起加入:
select d
from generate_series(timestamp '2013-12-01', timestamp '2013-12-31', interval '1 day') d;
http://www.postgresql.org/docs/current/static/functions-srf.html
对于上一行和下一行值,请查看lead()
和lag()
窗口函数:
select date_trunc('day', ts) as curr_row_day,
lag(date_trunc('day', ts)) over w as prev_row_day
from data
window w as (order by ts)
http://www.postgresql.org/docs/current/static/tutorial-window.html