从单个数据表中为每个单个帐户写出期间的所有天数

时间:2019-03-02 22:37:21

标签: tsql

我有一个数据表,其中包含多个银行帐户的每日交易记录。我想计算特定时段内每天在每个银行帐户上进行的交易总额。对于这段时间内没有交易的日子,我想查看一个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),然后才转到下一个帐户?

更新:我正在查看大量的银行帐户。帐户数量会随着时间而改变

1 个答案:

答案 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