我正在尝试计算过去X天每个日期response time
的中位数conversations
。
我在下面使用以下查询,但由于某种原因,它会生成多个具有相同日期的行。
with grouping as (
SELECT a.id, d.date, extract(epoch from (first_response_at - started_at)) as response_time
FROM (
select to_char(date_trunc('day', (current_date - offs)), 'YYYY-MM-DD') AS date
FROM generate_series(0, 2) AS offs
) d
LEFT OUTER JOIN apps a on true
LEFT OUTER JOIN conversations c ON (d.date=to_char(date_trunc('day'::varchar, c.started_at), 'YYYY-MM-DD')) and a.id = c.app_id
and c.app_id = a.id and c.first_response_at > (current_date - (2 || ' days')::interval)::date
)
select
*
from grouping
where grouping.id = 'ASnYW1-RgCl0I'
有什么想法吗?
答案 0 :(得分:2)
首先,您的查询存在许多问题,假设您没有向我们展示任何部分:
apps
开始,您只能使用与id
相同的列c.app_id
。您可以移除表apps
并选择c.app_id
以获得相同的结果。to_char()
时,您首先不必date_trunc()
到date
,to_char()
函数会处理此问题。generate_series()
也适用于timestamps
。只需输入带有间隔的日期值,然后在使用前将结果投放到date
。所以,删除所有的flotsam我们最终得到的与你问题中的查询完全相同,但现在我们至少可以看到发生了什么。
SELECT c.app_id, to_date(d.date, 'YYYY-MM-DD') AS date,
extract(epoch from (first_response_at - started_at)) AS response_time
FROM generate_series(CURRENT_DATE - 2, CURRENT_DATE, interval '1 day') d(date)
LEFT JOIN conversations c ON d.date::date = c.started_at::date
AND c.app_id = 'ASnYW1-RgCl0I'
AND c.first_response_at > CURRENT_DATE - 2;
您无法计算任何地方的中间响应时间,因此这是您需要解决的一个大问题。这只需要表conversations
中的数据,看起来有点像这样计算过去2天的中位响应时间:
SELECT app_id, started_at::date AS start_date,
percentile_disc(0.5) WITHIN GROUP (ORDER BY first_response_at - started_at) AS median_response
FROM conversations
WHERE app_id = 'ASnYW1-RgCl0I'
AND first_response_at > CURRENT_DATE - 2
GROUP BY 2;
当我们折叠两个查询,并将参数轻松地放在一个地方时,这是最终的结果:
SELECT p.id, to_date(d.date, 'YYYY-MM-DD') AS date,
extract(epoch from (c.median_response)) AS response_time
FROM (VALUES ('ASnYW1-RgCl0I', 2)) p(id, days)
JOIN generate_series(CURRENT_DATE - p.days, CURRENT_DATE, interval '1 day') d(date) ON true
LEFT JOIN LATERAL (
SELECT started_at::date AS start_date,
percentile_disc(0.5) WITHIN GROUP (ORDER BY first_response_at - started_at) AS median_response
FROM conversations
WHERE app_id = p.id
AND first_response_at > CURRENT_DATE - p.days
GROUP BY 2) c ON d.date::date = c.start_date;
如果您想更改应用的ID或要回顾的天数,您只需相应地更改VALUES
子句。您还可以将整个事物包装在SQL函数中,并将VALUES
子句转换为两个参数。