How to check a SQL CASE with multiple conditions?

2019-08-29 23:42发布

问题:

I have two tables. Accounts ACC and FinancialTrans FT

The FinancialTrans table is as follows:

AcctID  TransTypeCode   DateOfTrans
123     TOLL            2016-06-06 00:00:00.000
123     TOLL            2016-06-02 00:00:00.000
123     TOLL            2016-04-28 00:00:00.000
123     PYMT            2016-03-11 00:00:00.000
123     TOLL            2015-12-22 00:00:00.000
123     TOLL            2015-12-22 00:00:00.000

The requirement is:
When any Accounts have NO 'TOLL' or 'PYMT' in the last 2 years print 'Flag'

SELECT ACC.Field1
      ,ACC.Field2
      ,ACC.Field3
      ,ACC.Field4
      ,CASE WHEN  
        (SELECT Max(DateOfTrans) FROM FinanceTrans FT
         WHERE ACC.AccountID = FT.AcctID
               AND (TransTypeCode = 'TOLL' AND DateOfTrans >= DATEADD(year, -2, GETDATE()))
               AND (TransTypeCode = 'PYMT' AND DateOfTrans >= DATEADD(year, -2, GETDATE()))
             GROUP BY AcctID, TransTypeCode) IS NULL
        THEN 'Flag'
        ELSE ''
       AND AS NoNo_Flag

FROM Accounts ACC

WHERE Condition 1, Condition 2...

回答1:

try this one:

SELECT
    acc.*,
    CASE WHEN f.acctid IS NULL THEN 'flag' ELSE '' END AS flag_noTollOrPmt
FROM
    accounts acc LEFT OUTER JOIN
    (SELECT 
        AcctID, 
        MAX(DateOfTrans) AS max_dateOfTrans_TollOrPmt
    FROM 
        FinanceTrans 
    WHERE 
        DateOfTrans >= DATEADD(YEAR, -2, GETDATE()) AND
        TransTypeCode IN( 'TOLL' , 'PYMT') 
    GROUP BY 
        AcctID) f ON
    acc.acctid = f.acctid


回答2:

You should be using window functions. The logic is to look at the maximum date for the two transaction types. The flag then depends on the relationship to the current date.

select a.*,
       (case when max(case when transtype in ('TOLL', 'PYMT') then DateOfTrans end) over
                       (partition by acctid) >= dateadd(year, -2, getdate())
             then 0 else 1
        end) as flag
from accounts;


回答3:

I could be misunderstanding the question, in which case I can refine my answer. It seems like you just need to check for the existence, or not, of records in the the sub-query. So to that extent do you really need to do an aggregate? And, try using EXISTS:

SELECT ACC.Field1, ACC.Field2, ACC.Field3, ACC.Field4, 
       CASE WHEN NOT EXISTS
           (SELECT DateOfTrans 
            FROM FinanceTrans FT
            WHERE ACC.AccountID = FT.AcctID
                  AND (TransTypeCode = 'TOLL' AND DateOfTrans >= DATEADD(year, -2, GETDATE()))
                  AND (TransTypeCode = 'PYMT' AND DateOfTrans >= DATEADD(year, -2, GETDATE())))
       THEN 'Flag'
       ELSE ''
       END AS NoNo_Flag
FROM Accounts ACC
WHERE [*condition*]


回答4:

So this is how I resolved this issue:

I created a separate column for each, first and then stored those details in a temporary table.
Then I pulled data from the temporary table using conditions to create the flag.

My code is as follows:

SELECT ACC.Field1
      ,ACC.Field2
      ,ACC.Field3
      ,ACC.Field4
      ,(SELECT Max(DateOfTrans) FROM FinanceTrans FT
        WHERE ACC.AccountID = FT.AcctID
          AND TransTypeCode = 'TOLL'
        GROUP BY AcctID, TransTypeCode) LastTollDate
      ,(SELECT Max(DateOfTrans) FROM FinanceTrans FT
        WHERE ACC.AccountID = FT.AcctID
          AND TransTypeCode = 'PYMT'
        GROUP BY AcctID, TransTypeCode) LastPymtDate

INTO #Temp_Data

FROM Accounts ACC

WHERE Condition 1, Condition 2...



SELECT ACC.Field1
      ,ACC.Field2
      ,ACC.Field3
      ,ACC.Field4
      ,CASE WHEN LastTollDate >= DATEADD(year, -2, GETDATE())
        AND LastPymtDate >= DATEADD(year, -2, GETDATE())
        THEN 'Flag'
        ELSE ''
       END AS Flag

FROM #Temp_Data