获取给定日期列表的多个类别的值总和
Get sum of values for multiple categories for a given list of dates
我需要编写一个查询来获取给定日期列表中每个类别的值总和。如果某个类别的值不存在,我们应该从前一个日期获取值。基本上类似于“每个日期每个类别的最大值”。最终目标是趋势图。如果类别的先前值不存在,则将值设置为 0
即可。
见下表和结果:
类别
id
name
1
savings
2
cash
3
stocks
项目
id
categoryId
value
createdAt
1
1
100
2022-01-01
2
2
20
2022-01-01
3
3
500
2022-01-01
4
2
0
2022-01-02
5
3
1000
2022-01-03
结果
createdAt
total
2022-01-01
620
2022-02-02
600
2022-02-03
1100
要获得单个日期的结果,我可以这样做:
SELECT SUM(value) as total
FROM Category
LEFT JOIN (
SELECT id, categoryId, value
FROM Item
WHERE id IN (
SELECT MAX(id) FROM Item WHERE createdAt <= '2022-01-10' GROUP BY categoryId)
) items ON Category.id = items.categoryId;
我完全不知道如何处理多个日期,例如。如果我的输入是 2022 年 1 月的每一天。我 运行 在 MySQL 8.0.23。此外,如果这对于单个查询不可行,我会提出想法。你有什么建议吗?
试试这个:
with u as
(select id as categoryId from Category),
v as
(select distinct createdAt from Item),
w as
(select * from u cross join v),
x as
(select createdAt,
categoryId,
(select value
from Item
where categoryId = w.categoryId and createdAt <= w.createdAt
order by createdAt desc
limit 1) as value
from w)
select createdAt, sum(value) as total
from x
group by createdAt
基本上获取创建日期与categoryIds的所有组合,然后使用子查询获取每个categoryId最接近或相等日期的值。
一个Fiddle.
一个选项使用window函数如SUM() OVER ()
和LAG()
如
WITH i AS
(
SELECT SUM(`value`) OVER (PARTITION BY `createdAt`,`categoryId` ORDER BY `createdAt`) AS total_sofar,
LAG(`value`,1,0) OVER (PARTITION BY `categoryId` ORDER BY `createdAt`) AS lg,
`createdAt`
FROM Item
)
SELECT DISTINCT `createdAt`,
SUM(total_sofar) OVER (ORDER BY `createdAt`)-SUM(lg) OVER (ORDER BY `createdAt`) AS total
FROM i
ORDER BY `createdAt`
因为您有 MySQL 8.0 版的 DBMS。诀窍是分组(partitioning by categoryId
连同 LAG
在第一次查询时)
我需要编写一个查询来获取给定日期列表中每个类别的值总和。如果某个类别的值不存在,我们应该从前一个日期获取值。基本上类似于“每个日期每个类别的最大值”。最终目标是趋势图。如果类别的先前值不存在,则将值设置为 0
即可。
见下表和结果:
类别
id | name |
---|---|
1 | savings |
2 | cash |
3 | stocks |
项目
id | categoryId | value | createdAt |
---|---|---|---|
1 | 1 | 100 | 2022-01-01 |
2 | 2 | 20 | 2022-01-01 |
3 | 3 | 500 | 2022-01-01 |
4 | 2 | 0 | 2022-01-02 |
5 | 3 | 1000 | 2022-01-03 |
结果
createdAt | total |
---|---|
2022-01-01 | 620 |
2022-02-02 | 600 |
2022-02-03 | 1100 |
要获得单个日期的结果,我可以这样做:
SELECT SUM(value) as total
FROM Category
LEFT JOIN (
SELECT id, categoryId, value
FROM Item
WHERE id IN (
SELECT MAX(id) FROM Item WHERE createdAt <= '2022-01-10' GROUP BY categoryId)
) items ON Category.id = items.categoryId;
我完全不知道如何处理多个日期,例如。如果我的输入是 2022 年 1 月的每一天。我 运行 在 MySQL 8.0.23。此外,如果这对于单个查询不可行,我会提出想法。你有什么建议吗?
试试这个:
with u as
(select id as categoryId from Category),
v as
(select distinct createdAt from Item),
w as
(select * from u cross join v),
x as
(select createdAt,
categoryId,
(select value
from Item
where categoryId = w.categoryId and createdAt <= w.createdAt
order by createdAt desc
limit 1) as value
from w)
select createdAt, sum(value) as total
from x
group by createdAt
基本上获取创建日期与categoryIds的所有组合,然后使用子查询获取每个categoryId最接近或相等日期的值。
一个Fiddle.
一个选项使用window函数如SUM() OVER ()
和LAG()
如
WITH i AS
(
SELECT SUM(`value`) OVER (PARTITION BY `createdAt`,`categoryId` ORDER BY `createdAt`) AS total_sofar,
LAG(`value`,1,0) OVER (PARTITION BY `categoryId` ORDER BY `createdAt`) AS lg,
`createdAt`
FROM Item
)
SELECT DISTINCT `createdAt`,
SUM(total_sofar) OVER (ORDER BY `createdAt`)-SUM(lg) OVER (ORDER BY `createdAt`) AS total
FROM i
ORDER BY `createdAt`
因为您有 MySQL 8.0 版的 DBMS。诀窍是分组(partitioning by categoryId
连同 LAG
在第一次查询时)