sql - 应用 SUM(其中 date1 和 date2 之间的日期)
问题描述
我的桌子目前看起来像这样:
+---------+---------------+------------+------------------+
| Segment | Product | Pre_Date | ON_Prepaid |
+---------+---------------+------------+------------------+
| RB | 01. Auto Loan | 2020-01-01 | 10645976180.0000 |
| RB | 01. Auto Loan | 2020-01-02 | 4489547174.0000 |
| RB | 01. Auto Loan | 2020-01-03 | 1853117000.0000 |
| RB | 01. Auto Loan | 2020-01-04 | 9350258448.0000 |
+---------+---------------+------------+------------------+
我试图在 7 天内对“ON_Prepaid”的值求和,比如说从“2020-01-01”到“2020-01-07”。这是我尝试过的
drop table if exists ##Prepay_summary_cash
select *,
[1W_Prepaid] = sum(ON_Prepaid) over (partition by SEGMENT, PRODUCT order by PRE_DATE rows between 1 following and 7 following),
[2W_Prepaid] = sum(ON_Prepaid) over (partition by SEGMENT, PRODUCT order by PRE_DATE rows between 8 following and 14 following),
[3W_Prepaid] = sum(ON_Prepaid) over (partition by SEGMENT, PRODUCT order by PRE_DATE rows between 15 following and 21 following),
[1M_Prepaid] = sum(ON_Prepaid) over (partition by SEGMENT, PRODUCT order by PRE_DATE rows between 22 following and 30 following),
[1.5M_Prepaid] = sum(ON_Prepaid) over (partition by SEGMENT, PRODUCT order by PRE_DATE rows between 31 following and 45 following),
[2M_Prepaid] = sum(ON_Prepaid) over (partition by SEGMENT, PRODUCT order by PRE_DATE rows between 46 following and 60 following),
[3M_Prepaid] = sum(ON_Prepaid) over (partition by SEGMENT, PRODUCT order by PRE_DATE rows between 61 following and 90 following),
[6M_Prepaid] = sum(ON_Prepaid) over (partition by SEGMENT, PRODUCT order by PRE_DATE rows between 91 following and 181 following)
into ##Prepay_summary_cash
from ##Prepay1
如果日期是连续的,事情应该没问题;但是,“Pre_Date”中缺少一些日期(您知道银行在星期日不工作等)。
所以我正在尝试做类似的事情
[1W] = SUM(ON_Prepaid) over (where Pre_date between dateadd(d,1,Pre_date) and dateadd(d,7,Pre_date))
类似的东西。因此,如果 2020-01-05 本身没有记录,则结果应仅将 2020 年 1 月 1、2、3、4、6、7 的日期相加,而不是 1、2、3、4、6, 7,8(8 因为“第 7 行以下”)。或者例如,我在 30 天之内丢失了记录,那么所有这 30 条记录都应该加起来为 0。所以 45 天应该只返回 15 天的值。我已经尝试在整个论坛中查找,但答案还不够。你们能帮帮我吗?或者将我链接到问题已经解决的线程。
非常感谢。
解决方案
如果日期是连续的,事情应该没问题
然后让它们连续。将您的真实数据(分组为每天一行)加入您的日历表(制作一个,或使用递归 cte 为您生成来自 X 的 360 个日期的列表),您的查询将成功
WITH d as
(
SELECT *
FROM
(
SELECT *
FROM cal
CROSS JOIN
(SELECT DISTINCT segment s, product p FROM ##Prepay1) x
) c
LEFT JOIN ##Prepay1 p
ON
c.d = p.pre_date AND
c.segment = p.segment AND
c.product = p.product
WHERE
c.d BETWEEN '2020-01-01' AND '2021-01-01' -- date range on c.d not c.pre_date
)
--use d.d/s/p not d.pre_date/segment/product in your query (sometimes the latter are null)
select *,
[1W_Prepaid] = sum(ON_Prepaid) over (partition by s, s order by d.d rows between 1 following and 7 following),
...
CAL 只是一个包含单列日期的表格,每天一个,没有时间,延伸到过去/未来 n 千天
希望注意月份的天数是可变的,所以 6M 有点用词不当.. 将月份称为 180D、90D 等可能会更好
还想指出,您的查询将您的数据按行划分为组。如果要在行日期后最多 180 天执行求和,则需要提取一年的数据,以便在第 180 行(6 月)上,您可以使用 12 月的数据来求和(从 6 月开始,12 月为 6 个月)
然后,如果您想将查询限制为仅显示到 6 月(但包括从 6 月之后的 6 个月汇总的数据),则需要将其全部包装在子查询中。您不能在求和的查询中“在 jan 和 jun 之间的位置”,因为 where 子句在 window 子句之前完成(这样做会在求和之前删除 dec 数据)
其他一些数据库使这更容易,Oracle 和 Postgres 浮现在脑海中。他们可以在其他行的值与当前行的值有一定距离的范围内执行求和。SQL server 仅有效地支持基于行的索引而不是其值的距离(基于值的距离支持仅限于“具有相同值的行”,而不是“具有 n 高于或低于当前行”)。我想可以通过交叉应用或选择中的协调子来满足要求,尽管我会小心检查性能..
SELECT *,
(SELECT SUM(tt.a) FROM x tt WHERE t.x = tt.x AND tt.y = t.y AND tt.z BETWEEN DATEADD(d, 1, t.z) AND DATEADD(d, 7, t.z) AS 1W
FROM
x t
推荐阅读
- nativescript - 使用 nativescript-drop-down 插件时出错
- javascript - 服务器发送事件意外停止
- typescript - 确保字符串联合具有特定字符串文字的元素的映射类型
- html - 如果我在第一个上使用 mask-image,我如何将第二个 div 重叠在第一个上方?
- node.js - 与远程服务器进行 SSL 握手期间的 httpd 代理错误
- python - 如何将 python pygame 函数从字符串更改为 python 中的函数?
- python - python main 函数每两分钟运行一次,但有时 main 函数需要分析三分钟,它执行一半的 main 函数
- python - 如何从 python 打开一个 url 并让程序的其余部分运行?
- swiftui - 如何在 SwiftUI 中集成函数以使用输入字典创建可重用的代码
- android - 如何更改后退箭头按钮 - android