如何使用CASE语句在SQL Server中计算存储桶值

时间:2018-07-12 06:59:27

标签: sql-server tsql sql-server-2012 ssms-2012

我有一个像这样的“时间表”表,其中包含帐户=“ Acctxyz”的时间表:

Account   DueDate        Amount

Acctxyz   2018-03-09    3049.00 
Acctxyz   2018-03-23    17857.00    
Acctxyz   2018-04-06    17949.00    
Acctxyz   2018-04-20    18042.00    
Acctxyz   2018-05-04    18135.00    
Acctxyz   2018-05-18    18229.00    
Acctxyz   2018-06-01    18324.00    
Acctxyz   2018-06-15    18419.00    
Acctxyz   2018-06-29    18514.00    

我的输入日期应该是2017-07-09,输出应该在“帐户”列中,其他四个带有“金额”的字段应该根据与我的输入日期和“到期日期”之间的日期差汇总到四个存储桶中,如下所示;

 Account   Late   Arrears   SeriousArrears  NonPerforming 
 Acctxyz    ####   ####       ####           #### 
  • 后期应为日期差为2和30的金额之和
  • 欠款应为日期差为31和60的金额之和
  • SeriousArrears应该是日期差为60和90的金额之和
  • 不良表现应为日期差> = 91的金额之和

下面是我的工作

declare @Rundate date = '20180709'
select Account,
CASE WHEN DATEDIFF(D,@Rundate,DueDate) BETWEEN -2 AND -30 THEN SUM(Amount) ELSE 0 END as Late,  
CASE WHEN DATEDIFF(D,@Rundate,DueDate) BETWEEN -31 AND -60 THEN SUM(Amount) ELSE 0 END as Arrears,
CASE WHEN DATEDIFF(D,@Rundate,DueDate) BETWEEN -61 AND -90 THEN SUM(Amount) ELSE 0 END as SeriousArrears,
CASE WHEN DATEDIFF(D,@Rundate,DueDate) >= -91 THEN SUM(Amount) ELSE 0 END as NonPerforming
from Schedule
group by Acct,DueDateKey

我得到的输出是九行,所有字段都为零。

非常感谢如何实现例外的输出,请指出我在哪里犯错。

4 个答案:

答案 0 :(得分:1)

BETWEEN -2 AND -30表示一个大于-2且小于-30的数字。空无一人。您必须小心使用负值之间。更改您的DATEDIFF,以获取正日差。

尝试一下:

SELECT   Account ,
         CASE WHEN DATEDIFF(D, DueDate, @Rundate)
                   BETWEEN 2 AND 30 THEN SUM(Amount)
              ELSE 0
         END AS Late ,
         CASE WHEN DATEDIFF(D, DueDate, @Rundate)
                   BETWEEN 31 AND 60 THEN SUM(Amount)
              ELSE 0
         END AS Arrears ,
         CASE WHEN DATEDIFF(D, DueDate, @Rundate)
                   BETWEEN 61 AND 90 THEN SUM(Amount)
              ELSE 0
         END AS SeriousArrears ,
         CASE WHEN DATEDIFF(D, DueDate, @Rundate) >= 91 THEN SUM(Amount)
              ELSE 0
         END AS NonPerforming
FROM Schedule
GROUP BY Account, DueDate

更新:如果需要将一行作为结果集:

CREATE TABLE #Schedule
    (
        Account VARCHAR(10) ,
        DueDate DATE ,
        Amount DECIMAL(10, 2)
    );

INSERT INTO #Schedule ( Account ,
                        DueDate ,
                        Amount )
VALUES ( 'Acctxyz', '2018-03-09', 3049.00 ) ,
       ( 'Acctxyz', '2018-03-23', 17857.00 ) ,
       ( 'Acctxyz', '2018-04-06', 17949.00 ) ,
       ( 'Acctxyz', '2018-04-20', 18042.00 ) ,
       ( 'Acctxyz', '2018-05-04', 18135.00 ) ,
       ( 'Acctxyz', '2018-05-18', 18229.00 ) ,
       ( 'Acctxyz', '2018-06-01', 18324.00 ) ,
       ( 'Acctxyz', '2018-06-15', 18419.00 ) ,
       ( 'Acctxyz', '2018-06-29', 18514.00  );

DECLARE @Rundate DATE = '20180709';
SELECT   t.Account ,
         SUM(Late) AS Late ,
         SUM(Arrears) AS Late ,
         SUM(SeriousArrears) AS SeriousArrears ,
         SUM(NonPerforming) AS NonPerforming
FROM     (   SELECT   Account ,
                      CASE WHEN DATEDIFF(D, DueDate, @Rundate)
                                BETWEEN 2 AND 30 THEN SUM(Amount)
                           ELSE 0
                      END AS Late ,
                      CASE WHEN DATEDIFF(D, DueDate, @Rundate)
                                BETWEEN 31 AND 60 THEN SUM(Amount)
                           ELSE 0
                      END AS Arrears ,
                      CASE WHEN DATEDIFF(D, DueDate, @Rundate)
                                BETWEEN 61 AND 90 THEN SUM(Amount)
                           ELSE 0
                      END AS SeriousArrears ,
                      CASE WHEN DATEDIFF(D, DueDate, @Rundate) >= 91 THEN
                               SUM(Amount)
                           ELSE 0
                      END AS NonPerforming
             FROM     #Schedule
             GROUP BY Account ,
                      DueDate ) t
GROUP BY t.Account;

DROP TABLE #Schedule;

结果:

+---------+----------+----------+----------------+---------------+
| Account |   Late   |   Late   | SeriousArrears | NonPerforming |
+---------+----------+----------+----------------+---------------+
| Acctxyz | 36933.00 | 36553.00 | 36177.00       | 38855.00      |
+---------+----------+----------+----------------+---------------+

答案 1 :(得分:1)

由于负值,您正在错误地操作BETWEEN。检查以下内容:

declare @Rundate date = '20180709'
select Account,DATEDIFF(D,@Rundate,DueDate),
Sum(CASE WHEN DATEDIFF(D,@Rundate,DueDate) BETWEEN -30 AND -2 THEN Amount ELSE 0 END) as Late,  
Sum(CASE WHEN DATEDIFF(D,@Rundate,DueDate) BETWEEN -60 AND -31 THEN Amount ELSE 0 END) as Arrears,
Sum(CASE WHEN DATEDIFF(D,@Rundate,DueDate) BETWEEN -90 AND -61 THEN Amount ELSE 0 END) as SeriousArrears,
Sum(CASE WHEN DATEDIFF(D,@Rundate,DueDate) <= -91 THEN Amount ELSE 0 END) as NonPerforming
from #Schedule
group by Account,DueDate   

答案 2 :(得分:1)

Arvo

这可能是您正在寻找的解决方案

架构:

SELECT * INTO #Schedule FROM (
SELECT 'Acctxyz' Account,'2018-03-09' DueDate,3049.00 Amount  UNION ALL
SELECT 'Acctxyz','2018-03-23',17857.00 UNION ALL    
SELECT 'Acctxyz','2018-04-06',17949.00 UNION ALL    
SELECT 'Acctxyz','2018-04-20',18042.00 UNION ALL    
SELECT 'Acctxyz','2018-05-04',18135.00 UNION ALL    
SELECT 'Acctxyz','2018-05-18',18229.00 UNION ALL    
SELECT 'Acctxyz','2018-06-01',18324.00 UNION ALL    
SELECT 'Acctxyz','2018-06-15',18419.00 UNION ALL    
SELECT 'Acctxyz','2018-06-29',18514.00
)A

查询:

Declare @Rundate  date = '20180709'
select Account,
SUM(CASE WHEN DATEDIFF(D,@Rundate,DueDate) BETWEEN -30 AND -2 THEN Amount ELSE 0 END) as Late,  
SUM(CASE WHEN DATEDIFF(D,@Rundate,DueDate) BETWEEN -60 AND -31 THEN Amount ELSE 0 END) as Arrears,
SUM(CASE WHEN DATEDIFF(D,@Rundate,DueDate) BETWEEN -90 AND -61 THEN Amount ELSE 0 END) as SeriousArrears,
SUM(CASE WHEN DATEDIFF(D,@Rundate,DueDate) >= -91 THEN Amount ELSE 0 END) as NonPerforming
from #Schedule
group by Account 

结果:

Account Late    Arrears SeriousArrears  NonPerforming
Acctxyz 36933.00    36553.00    36177.00    109663.00

答案 3 :(得分:0)

感谢您的所有建议,确实有帮助,我从您的所有建议中得出了以下答案;

select Account,
    sum (case WHEN DATEDIFF(D, DueDate, @Rundate)  BETWEEN 2 AND 30 THEN Amount else 0  end) as late,
    sum (case WHEN DATEDIFF(D, DueDate, @Rundate)  BETWEEN 31 AND 60 THEN Amount else 0  end) as Arrears,
    sum (case WHEN DATEDIFF(D, DueDate, @Rundate)  BETWEEN 61 AND 90 THEN Amount else 0  end) as SeriousArrears,
    sum (case WHEN DATEDIFF(D, DueDate, @Rundate)  >= 91 THEN Amount else 0  end) as NonPerforming
from #schedule
group by Account