如何使用 CASE 语句计算 SQL 服务器中的存储桶值

How to calculate bucket values in SQL server using CASE statement

我有一个像这样的 'Schedule' table 帐户计划 = '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 列,其他四个字段的金额应该根据与我的输入日期和截止日期的日期差异在四个桶中汇总,如下所示;

 Account   Late   Arrears   SeriousArrears  NonPerforming 
 Acctxyz    ####   ####       ####           #### 

下面是我所做的;

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

我得到一个包含九行且所有字段都为零的输出。

非常感谢如何实现异常输出,请指出我哪里出错了。

BETWEEN -2 AND -30表示大于-2小于-30的数。有none。您必须小心使用带有负值的 between 。更改您的 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      |
+---------+----------+----------+----------------+---------------+

由于负值,您 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   

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

感谢您的所有建议,它真的很有帮助,我从您的所有建议中得出以下答案;

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