How to query this output in SQL server

后端 未结 4 1872
不思量自难忘°
不思量自难忘° 2021-02-06 18:33

I have a table with data like this:

CREATE TABLE Test
    (CustName varchar(20), Country varchar(20), RecordedTime datetime, CurrNo tinyint);

INSERT INTO Test
          


        
4条回答
  •  走了就别回头了
    2021-02-06 19:23

    From what I understand from the different scenario's, they can be achieved by basically only 2 rules.

    • Rule 1: The records for a CustName with the RecordedTime all on the same day.
    • Rule 2: The records for a CustName with the RecordedTime over more than one day.

    With a few window functions and an OR in the outer query, we can have two rules to target all scenarios.

    And then use CASE WHEN to calculate the "Audit" and the "History".

     SELECT
      CustName, Country, 
      FORMAT(RecordedTime, 'yyyy-MMM-dd hh:mm tt') as RecordedTime,
      (CASE CurrNo 
       WHEN 1 then 'ADD'
       ELSE 'CHANGE'
       END) as [Audit],
      (CASE  
       WHEN CurrNo = 1 then 'NEW'
       WHEN ReverseCurrRN = 1 then 'CURRENT'
       ELSE 'BEFORE'
       END) as [History]
       --, CurrNo, ReverseCurrRN, MinCurrNoPerCust, MaxCurrNoPerCustDate ,MinCurrNoPerCust, MinDatePerCust, MaxDatePerCust
     FROM
     (
        SELECT CustName, Country, RecordedTime, CurrNo
          ,ROW_NUMBER() OVER (PARTITION BY CustName ORDER BY CurrNo DESC) AS ReverseCurrRN
          ,MIN(CurrNo) OVER (PARTITION BY CustName) AS MinCurrNoPerCust
          ,MAX(CurrNo) OVER (PARTITION BY CustName, cast(RecordedTime AS DATE)) AS MaxCurrNoPerCustDate
          ,CAST(MIN(RecordedTime) OVER (PARTITION BY CustName) AS DATE) AS MinDatePerCust
          ,CAST(MAX(RecordedTime) OVER (PARTITION BY CustName) AS DATE) AS MaxDatePerCust
        FROM Test t
        WHERE CAST(RecordedTime AS DATE) between DATEADD(day,-1,@Date) and @Date
     ) q
     WHERE MaxDatePerCust = @Date
     AND (
        -- Scenario 1 & 2 & 4 & 6
           (MinDatePerCust = MaxDatePerCust AND (ReverseCurrRN = 1 OR CurrNo = MinCurrNoPerCust OR (MinCurrNoPerCust = 1 AND ReverseCurrRN = 2)))
        -- Scenario 2 & 3 & 5 & 7 & 8
        OR (MinDatePerCust != MaxDatePerCust AND (ReverseCurrRN = 1 OR CurrNo = 1 OR CurrNo = MaxCurrNoPerCustDate))
     )
     ORDER BY MinDatePerCust, CustName, CurrNo;
    

    You can test it on db<>fiddle here

提交回复
热议问题