我有一个查询,试图查找一组服务地点的平均能耗,这些服务地点在特定月份内每个服务地点的能耗差异在 ±5% 之内。我知道 range 和 rows 函数无法定义特定的数字范围,而是使用前面和后面的子句,但是我如何编写这个查询来满足我的需要?
WITH energy_consumption_cte AS (
SELECT
sl.id,
sl.sqft,
SUM(CASE WHEN dl.log_label = 'energy use' THEN dl.value END) AS monthly_consumption
FROM
serv_location sl
INNER JOIN
device d ON d.service_loc_id = sl.id
INNER JOIN
device_log dl ON dl.device_id = d.id
WHERE
dl."timestamp" >= '2022-08-01 00:01:00.000'::timestamp
AND dl."timestamp" < '2022-09-01 00:01:00.000'::timestamp
AND sl.sqft IS NOT NULL
GROUP BY
sl.id, sl.sqft
)
SELECT
id,
sqft,
monthly_consumption,
(monthly_consumption / AVG(monthly_consumption) OVER w) * 100
AS average_monthly_for_sqft_range
FROM
energy_consumption_cte
window w as (PARTITION BY sqft ORDER BY sqft range between
ROUND(sqft * 0.95) and ROUND(sqft * 1.05))
ORDER BY
sqft ASC;
range
模式可以定义特定范围。要使用包含与当前记录相比向上/向下 5% 的记录值的聚合函数,您应该想到 range between 0.05*sqft preceding and 0.05*sqft following
。问题是,你不能在那里使用变量。
在 offset
和 offsetPRECEDING
框架选项中,offset 必须是不包含任何变量、聚合函数或窗口函数的表达式。FOLLOWING
如果您尝试引用
sqft
列/字段,您将得到:
ERROR: argument of RANGE must not contain variables LINE 27: RANGE BETWEEN sqft*0.05 PRECEDING ^
lag()
或 lead()
计算行与行之间的百分比变化来解决该限制,然后将其收集到步进 sum()
中,以便它保持 sqft
的初始顺序。一旦你有了这个,你可以在框架子句中使用常量偏移来达到 5% 来回。 db<>fiddle 的演示:
WITH energy_consumption_cte AS (
SELECT sl.id,
sl.sqft,
SUM(dl.value)filter(where dl.log_label='energy use') AS monthly_consumption
FROM serv_location sl
INNER JOIN device d ON d.service_loc_id = sl.id
INNER JOIN device_log dl ON dl.device_id = d.id
WHERE dl."timestamp" >= '2022-08-01 00:01:00.000'::timestamp
AND dl."timestamp" < '2022-09-01 00:01:00.000'::timestamp
AND sl.sqft IS NOT NULL
GROUP BY sl.id, sl.sqft
),square_footage_steps_cte AS (
SELECT *, 1-lag(sqft,1,sqft)over(order by sqft)/sqft::numeric AS sqft_step
FROM energy_consumption_cte
ORDER BY sqft ASC
),square_footage_steps_cumulative_cte AS (
SELECT *, sum(sqft_step)over(order by sqft) AS sqft_step_sum
FROM square_footage_steps_cte
ORDER BY sqft ASC)
SELECT id,
sqft,
monthly_consumption,
AVG(monthly_consumption) OVER w AS average_monthly_for_sqft_range,
array_agg(id)over w as rows_in_frame
FROM square_footage_steps_cumulative_cte
WINDOW w as (ORDER BY sqft_step_sum
RANGE BETWEEN 0.05 PRECEDING
AND 0.05 FOLLOWING)
ORDER BY sqft ASC;
id | 平方英尺 | 每月_消费 | 平方英尺范围的平均每月 | 帧内行数 |
---|---|---|---|---|
1 | 100 | 400 | 700.0000000000000000 | {1,2} |
2 | 105 | 1000 | 1000.0000000000000000 | {1,2,3} |
3 | 110 | 1600 | 1600.0000000000000000 | {2,3,4} |
4 | 115 | 2200 | 1900.0000000000000000 | {3,4} |
5 | 200 | 2800 | 3100.0000000000000000 | {5,6} |
6 | 210 | 3400 | 3100.0000000000000000 | {5,6} |