我有一个包含userName和entry_data (包含值和entryDate的JSON用户输入)的数据库。
下面是表的一个示例:
| userName | value | entryDate |
| ________ | _____ | __________|
| Aaron | 1234 | 7/25/2022 |
| Aaron | 6463 | 7/26/2022 |
| Aaron | 8375 | 7/27/2022 |
| Aaron | 2734 | 7/28/2022 |
| Aaron | 4563 | 7/29/2022 |
| Aaron | 7374 | 7/30/2022 |
| Aaron | 8923 | 7/31/2022 |
| Aaron | 6737 | 8/1/2022 |
| Aaron | 1374 | 8/2/2022 |
| Aaron | 1834 | 8/3/2022 |
| Aaron | 3646 | 8/4/2022 |
| Aaron | 7834 | 8/5/2022 |
| Aaron | 2473 | 8/6/2022 |
| Aaron | 4673 | 8/7/2022 |我的任务是求和值(totalValue),按周(7/25-7/31 = week1Value,8/1-8/7 = week2Value)求和值,并逐周查找不同的值(week2Value - week1Value = WoWDifference),因此如下所示:
| userName | totalValue | week1Value | week2Value | WoWDifference |
| ________ | __________ | __________ | __________ | _____________ |
| Aaron | 76,071 | 39,666 | 36,405 | -3,261 | 我不熟悉“分组”和减去日期范围内的值。到目前为止,我是这样对事物进行分组的:
SELECT
userName,
cast((entry_data ->> 'value') as Int) as totalValue,
case
when (entry_data ->> 'week1Value')::DATE BETWEEN '2022-07-25' AND '2022-07-31' then 'week1'
when (entry_data ->> 'week2Value')::DATE BETWEEN '2022-08-01' AND '2022-08-07' then 'week2'
end as timeframe,
FROM entry输出:
| userName | totalValue | timeframe|
| ________ | __________ | ________ |
| Aaron | 39,666 | week1 |
| Aaron | 36,405 | week2 |如何按周提取totalValue之和,以得到周之间的差额?
发布于 2022-08-03 23:12:36
试试这个:
SELECT
userName,
sum(entry_data ->> 'value') as totalValue,
case when (entry_data ->> 'week1Value')::DATE BETWEEN '2022-07-25' AND '2022-07-31'
then sum(entry_data ->> 'value') AS week1 /* changed */
case when (entry_data ->> 'week2Value')::DATE BETWEEN '2022-08-01' AND '2022-08-07'
then sum(entry_data ->> 'value') AS week2 /* changed */
FROM entry
group by userName /* changed */发布于 2022-08-05 00:02:34
另一种方法(类似于@Y )假设日期是连续的。
with data as
(select *, ceil(row_number() over (order by 0)::decimal/7)::integer rn
from entry)
select username,sum(to_number(entry_data->>'value','9999999')) total_value,
sum (case when rn = 1 then
to_number(entry_data->>'value','9999999')
else 0
end) week_1_total,
sum (case when rn = 2 then
to_number(entry_data->>'value','9999999')
else 0
end) week_2_total
from data
group by username;或者,使用CROSSTAB使用下面的查询-
SELECT *
FROM crosstab(
'SELECT username, total_value,
week_no, total_weekly
FROM (
with data as (
select e.username, e.rn week_no,
(select sum(to_number(entry_data->>$$value$$,$$9999999$$))
from entry) total_value,
sum(to_number(entry_data->>$$value$$,$$9999999$$)) total_weekly
from
(select *,
ceil(row_number() over
(partition by username order by 0)::decimal/7)::integer rn
from entry) e
group by
e.username, total_value, e.rn
)
select username,
week_no,
total_value,
total_weekly
from data
union all
select username,
(select max(week_no) from data) +
row_number() over (partition by username order by 0),
total_value,
total_weekly - coalesce(lag(total_weekly) over (order by week_no), 0)
from data ) x
ORDER BY 1'
,$$VALUES (1), (2), (3), (4), (5), (6)$$
) AS ct
("username" text,
"total_value" int,
"Week_1" int,
"Week_2" int,
"Week_3" int,
"Weekdiff_1" int,
"Weekdiff_2" int,
"Weekdiff_3" int
);请参阅小提琴这里。
上面的小提琴还探索了案例外推数据使用crosstab和手动方法的枢轴。
仍然有一些以上可能无法处理的情况,例如如果有少于7行或它没有整整一周,但它提供了一种通用的方法,可以修改以满足特定的用例。
values clause of crosstab中的硬编码也可以用一个查询来代替,以生成一个值的两倍的数字列表,因为给定的用户名有几周的时间。
https://stackoverflow.com/questions/73227825
复制相似问题