我有一个数据表,其中包含多个银行帐户的每日交易记录。我想计算特定时段内每天在每个银行帐户上进行的交易总额。对于这段时间内没有交易的日子,我想查看一个NULL值。
我正在使用两个表:一个包含交易数据,另一个包含日历表。
使用下面显示的代码(ZWID是银行帐户的ID),我能够为单个帐户获得理想的结果
WITH sum_transactions as
(
SELECT csd.ZWID, csd.ValueDate, sum_total = sum(csd.amount)
FROM myDataBase.CashData as csd
WHERE csd.ValueDate > '20190131' and csd.ValueDate <= '20190208'
AND csd.ZWID IN (1592)
GROUP BY csd.ZWID, csd.ValueDate
)
SELECT st.zwid, cal.Calendar_Date, st.sum_total
FROM treasury.dbo.calendar as cal
LEFT JOIN sum_transactions as st on st.ValueDate = cal.Calendar_Date
WHERE cal.Calendar_Date > '20190131' and cal.Calendar_Date<= '20190208'
ORDER BY 1, 2
我得到以下(期望的)输出:
zwid Calendar_Date sum_total
1592 2019-02-01 606174,09
NULL 2019-02-02 NULL
NULL 2019-02-03 NULL
1592 2019-02-04 -600000
NULL 2019-02-05 NULL
NULL 2019-02-06 NULL
NULL 2019-02-07 NULL
NULL 2019-02-08 NULL
即在此期间,该特定银行帐户有两天的交易记录。
现在,当我向IN语句中添加第二个帐户(ID 1593)时,我希望获得第二组8个新行(2月1日至2月8日),且总和或为NULL值(两个帐户共16行)。
但是,我现在得到一个结果表,该结果表不再显示第一个帐户的行(具有两个值均不显示任何交易的两天)。
zwid Calendar_date sum_total
NULL 2019-02-02 NULL
NULL 2019-02-03 NULL
1592 2019-02-04 -600000
1592 2019-02-01 606174,09
1593 2019-02-01 -847958,75
1593 2019-02-04 303105,26
1593 2019-02-05 -285312,64
1593 2019-02-06 502762,95
1593 2019-02-07 405372,02
1593 2019-02-08 326213,87
很显然,我无法成功地使查询分别为每个帐户写入所有日期。
如何更改查询以使其通过一个银行帐户运行,写出该期间的所有天数(值或NULL),然后才转到下一个帐户?
更新:我正在查看大量的银行帐户。帐户数量会随着时间而改变
答案 0 :(得分:1)
我认为这可能是您需要的,请尝试一下并告诉我。但是基本上,我必须在要查找的ID /日期的完整列表中使用CROSS APPLY
,然后使用其余的代码来获得所需的结果:
DROP TABLE IF EXISTS #Test;
DROP TABLE IF EXISTS #FullCalendar;
CREATE TABLE #Test
(
ZWID INT ,
ValueDate DATE ,
Amount MONEY
);
INSERT INTO #Test ( ZWID ,
ValueDate ,
Amount )
VALUES ( 1, '20190101', 100.00 ) ,
( 1, '20190101', 75.00 ) ,
( 1, '20190108', 75.00 ) ,
( 1, '20190110', 50.00 ) ,
( 2, '20190101', 25.00 ) ,
( 2, '20190102', 35.00 ) ,
( 2, '20190103', 50.00 ) ,
( 2, '20190103', 125.00 ) ,
( 3, '20190102', 150.00 ) ,
( 3, '20190109', 100.00 ) ,
( 3, '20190110', 75.00 ) ,
( 3, '20190110', 75.00 );
SELECT dd.Date, t.ZWID
INTO #FullCalendar
FROM dbo.DateDimension AS dd
CROSS APPLY #Test AS t
WHERE dd.Date >= '20190101' AND dd.Date < '20190111'
GROUP BY dd.Date ,
t.ZWID
--SELECT * FROM #FullCalendar ORDER BY ZWID, Date
;WITH sum_trans AS (
SELECT
t.ZWID, t.ValueDate, sum_total = SUM(t.Amount)
FROM #Test AS t
GROUP BY t.ZWID ,
t.ValueDate )
SELECT fc.Date, fc.ZWID, st.sum_total
FROM #FullCalendar AS fc
LEFT OUTER JOIN sum_trans AS st ON st.ZWID = fc.ZWID AND fc.Date = st.ValueDate
ORDER BY fc.ZWID,fc.Date;
在这里也留下我的老答案。
通过使用2个CTE和UNION ALL,我能够获得您想要的结果:
WITH sum_transactions as
(
SELECT csd.ZWID, csd.ValueDate, sum_total = sum(csd.amount)
FROM myDataBase.CashData as csd
WHERE csd.ValueDate > '20190131' and csd.ValueDate <= '20190208'
AND csd.ZWID IN (1592)
GROUP BY csd.ZWID, csd.ValueDate
) ,
WITH sum_transactions2 as
(
SELECT csd.ZWID, csd.ValueDate, sum_total = sum(csd.amount)
FROM myDataBase.CashData as csd
WHERE csd.ValueDate > '20190131' and csd.ValueDate <= '20190208'
AND csd.ZWID IN (1593)
GROUP BY csd.ZWID, csd.ValueDate
)
SELECT st.zwid, cal.Calendar_Date, st.sum_total
FROM treasury.dbo.calendar as cal
LEFT JOIN sum_transactions as st on st.ValueDate = cal.Calendar_Date
WHERE cal.Calendar_Date > '20190131' and cal.Calendar_Date<= '20190208'
ORDER BY 1, 2
UNION ALL
SELECT st.zwid, cal.Calendar_Date, st.sum_total
FROM treasury.dbo.calendar as cal
LEFT JOIN sum_transactions2 as st on st.ValueDate = cal.Calendar_Date
WHERE cal.Calendar_Date > '20190131' and cal.Calendar_Date<= '20190208'
ORDER BY 1, 2