"distinct on" 按 postgres 分组
"distinct on" with group by postgres
我有以下记录:
id run_hour performance_hour value
2 "2017-06-25 09:00:00" "2017-06-25 07:00:00" 6
2 "2017-06-25 09:00:00" "2017-06-25 08:00:00" 5
1 "2017-06-25 09:00:00" "2017-06-25 08:00:00" 5
2 "2017-06-25 08:00:00" "2017-06-25 07:00:00" 5
1 "2017-06-25 08:00:00" "2017-06-25 07:00:00" 5
我们 运行 每小时查看当前小时和前几个小时的每个 id 的结果。
仅当与前一小时相比发生变化时 运行 我们才插入新记录
(我们不想覆盖该值,因为我们想测量 1 小时或 2 小时等后的值。
我想对每个 id 的最新可用值求和(按 run_hour 排序)- 值。
在上面的示例中,运行 9:00 的广告 1 和 7:00 的表演时间没有记录 - 因为它与 运行 的 8:00 和 7:00
的表演时间
在上面的例子中,如果我要求 运行 2017-06-25 09:00:00 的总和,我希望得到:
id, value
1 10
2 11
对于id 1,计算出来的是10:(run_hour<2017-06-25 08:00:00> + run_hour<2017-06-25 09:00:00>) 对于 id 2,它是 11 计算出来的:(run_hour<2017-06-25 09:00:00> + run_hour<2017-06-25 09:00:00>)
我写了以下查询:
select distinct on (id, run_hour) id, sum(value) from metrics where run_hour <= '2017-06-25 09:00' and performance_hour >= '2017-06-25 07:00' and performance_hour < '2017-06-25 09:00'
group by id
order by id, run_hour
但是我得到一个错误,run_hour 也必须在 GROUP BY 子句中。 - 但如果我添加它,我会得到不正确的数据 - 还有我不需要的前几小时的数据 - 我需要有数据的最新一小时。
如何将 "distinct on" 与分组依据一起使用?
你想要 distinct on
在 之前 group by
:
select id, sum(value)
from (select distinct on (id, run_hour) m.*
from metrics m
where run_hour <= '2017-06-25 09:00' and
performance_hour >= '2017-06-25 07:00' and
performance_hour < '2017-06-25 09:00'
order by id, run_hour, performance_hour desc
) m
group by id;
任务很复杂。假设您希望从以下数据中获得 7:00 到 9:00 的表演时间:
id run_hour performance_hour value
2 "2017-06-25 09:00:00" "2017-06-25 06:00:00" 6
2 "2017-06-25 09:00:00" "2017-06-25 10:00:00" 5
预期结果为 18(7:00 为 6 + 8:00 为 6 + 9:00 为 6)全部基于本身位于外部的 6:00 记录所需的时间范围。
我们需要一个递归的 CTE,从每个 id 的第一个想要的表演时间开始,直到最后一个想要的表演时间。因此我们建立了不存在的记录,我们可以稍后总结。
with recursive cte(id, run_hour, performance_hour, value) as
(
select *
from
(
select distinct on (id)
id,
run_hour,
greatest(performance_hour, timestamp '2017-06-25 07:00') as performance_hour,
value
from metrics
where run_hour = timestamp '2017-06-25 09:00'
and performance_hour <= timestamp '2017-06-25 07:00'
order by id, metrics.performance_hour desc
) start_by_id
union all
select
cte.id,
cte.run_hour,
cte.performance_hour + interval '1 hour' as performance_hour,
coalesce(m.value, cte.value) as value
from cte
left join metrics m on m.id = cte.id
and m.run_hour = cte.run_hour
and m.performance_hour = cte.performance_hour + interval '1 hour'
where cte.performance_hour < timestamp '2017-06-25 09:00'
)
select id, sum(value)
from cte
group by id;
Rextester link:http://rextester.com/PHC88770
我有以下记录:
id run_hour performance_hour value
2 "2017-06-25 09:00:00" "2017-06-25 07:00:00" 6
2 "2017-06-25 09:00:00" "2017-06-25 08:00:00" 5
1 "2017-06-25 09:00:00" "2017-06-25 08:00:00" 5
2 "2017-06-25 08:00:00" "2017-06-25 07:00:00" 5
1 "2017-06-25 08:00:00" "2017-06-25 07:00:00" 5
我们 运行 每小时查看当前小时和前几个小时的每个 id 的结果。
仅当与前一小时相比发生变化时 运行 我们才插入新记录 (我们不想覆盖该值,因为我们想测量 1 小时或 2 小时等后的值。
我想对每个 id 的最新可用值求和(按 run_hour 排序)- 值。
在上面的示例中,运行 9:00 的广告 1 和 7:00 的表演时间没有记录 - 因为它与 运行 的 8:00 和 7:00
的表演时间在上面的例子中,如果我要求 运行 2017-06-25 09:00:00 的总和,我希望得到:
id, value
1 10
2 11
对于id 1,计算出来的是10:(run_hour<2017-06-25 08:00:00> + run_hour<2017-06-25 09:00:00>) 对于 id 2,它是 11 计算出来的:(run_hour<2017-06-25 09:00:00> + run_hour<2017-06-25 09:00:00>) 我写了以下查询:
select distinct on (id, run_hour) id, sum(value) from metrics where run_hour <= '2017-06-25 09:00' and performance_hour >= '2017-06-25 07:00' and performance_hour < '2017-06-25 09:00'
group by id
order by id, run_hour
但是我得到一个错误,run_hour 也必须在 GROUP BY 子句中。 - 但如果我添加它,我会得到不正确的数据 - 还有我不需要的前几小时的数据 - 我需要有数据的最新一小时。
如何将 "distinct on" 与分组依据一起使用?
你想要 distinct on
在 之前 group by
:
select id, sum(value)
from (select distinct on (id, run_hour) m.*
from metrics m
where run_hour <= '2017-06-25 09:00' and
performance_hour >= '2017-06-25 07:00' and
performance_hour < '2017-06-25 09:00'
order by id, run_hour, performance_hour desc
) m
group by id;
任务很复杂。假设您希望从以下数据中获得 7:00 到 9:00 的表演时间:
id run_hour performance_hour value 2 "2017-06-25 09:00:00" "2017-06-25 06:00:00" 6 2 "2017-06-25 09:00:00" "2017-06-25 10:00:00" 5
预期结果为 18(7:00 为 6 + 8:00 为 6 + 9:00 为 6)全部基于本身位于外部的 6:00 记录所需的时间范围。
我们需要一个递归的 CTE,从每个 id 的第一个想要的表演时间开始,直到最后一个想要的表演时间。因此我们建立了不存在的记录,我们可以稍后总结。
with recursive cte(id, run_hour, performance_hour, value) as
(
select *
from
(
select distinct on (id)
id,
run_hour,
greatest(performance_hour, timestamp '2017-06-25 07:00') as performance_hour,
value
from metrics
where run_hour = timestamp '2017-06-25 09:00'
and performance_hour <= timestamp '2017-06-25 07:00'
order by id, metrics.performance_hour desc
) start_by_id
union all
select
cte.id,
cte.run_hour,
cte.performance_hour + interval '1 hour' as performance_hour,
coalesce(m.value, cte.value) as value
from cte
left join metrics m on m.id = cte.id
and m.run_hour = cte.run_hour
and m.performance_hour = cte.performance_hour + interval '1 hour'
where cte.performance_hour < timestamp '2017-06-25 09:00'
)
select id, sum(value)
from cte
group by id;
Rextester link:http://rextester.com/PHC88770