How to query this output in SQL server

后端 未结 4 2005
不思量自难忘°
不思量自难忘° 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:32

    Based on my understanding, Below is the logic for your required output

    step 1

    • get max(CurrNo) for given date for each custName.
    • here it is cte.

    step 2

    • get first entered record for the mentioned date for All CustNames available in cte if any.
    • in the union of above record, get last edited record for records edited less than the current date for All CustNames available in cte if any.
    • here it is cte2.

    step 3

    • get records from #test table where currNo=maximun or currno=1 from this step, you will get last updated records and any newly added record if any for given date.
    • here it is the first query after cte and cte2.

    step 4

    • get first added record for given date if any with Audit as change and History as Before.
    • this is for custom special case requirement
    • here it is the second query.

    step 5

    • get the first record from cte2 to get one records for previously edited record for given date.
    • here it is the third query.

    -

    CREATE TABLE #Test
        (CustName varchar(20), Country varchar(20), RecordedTime datetime, CurrNo tinyint);
    
    
    INSERT INTO #Test
        (CustName, Country, RecordedTime, CurrNo)
    VALUES
        ('Alex', 'Australia', '2018-06-01 08:00:00', 1),
        ('Alex', 'China', '2018-06-01 10:00:00', 2),
        ('Alex', 'India', '2018-06-01 10:05:00', 3),
        ('Alex', 'Japan', '2018-06-01 11:00:00', 4),
        ('John', 'Australia', '2018-06-01 08:00:00', 1),
        ('John', 'China', '2018-06-02 08:00:00', 2),
        ('Bob', 'Australia', '2018-06-02 09:00:00', 1),
        ('Bob', 'Brazil', '2018-06-03 09:50:00', 2),
        ('Bob', 'Africa', '2018-06-03 11:50:00', 3),
        ('Bob', 'India', '2018-06-03 00:55:00', 4),
        ('Tim', 'Brazil', '2018-06-10 00:00:00', 2),
        ('Tim', 'Cuba', '2018-06-11 00:00:00', 3),
        ('Tim', 'India', '2018-06-11 00:05:00', 4),
        ('Jerry', 'Cuba', '2018-06-12 00:00:00', 4),
        ('Jerry', 'Brazil', '2018-06-12 00:05:00', 5),
        ('Jerry', 'India', '2018-06-12 00:10:00', 7),
        ('Jerry', 'USA', '2018-06-12 00:15:00', 9),
        ('Maulik', 'Aus', '2018-06-12 00:00:00',3),
        ('Maulik', 'Eng', '2018-06-13 00:00:00',4),
        ('Maulik', 'USA', '2018-06-14 00:00:00',5),
        ('Maulik', 'Ind', '2018-06-14 00:00:00',6);
    
    select * from #Test
    
       declare @selectedDate date='2018-06-14';
    with cte as
    (
    select CustName,max(CurrNo) maxno,count(1) cnt
    from #Test where datediff(day,RecordedTime,@selectedDate)=0 
    group by CustName
    ),cte2 as (
    select top 1 t.*,cnt
     from #Test t join cte c on c.CustName =t.CustName
    where datediff(day,RecordedTime,@selectedDate)>0 and t.CurrNo!=c.maxno
    order by t.RecordedTime  desc
    union select top 1 t.*,cnt
     from #Test t join cte c on c.CustName =t.CustName
    where datediff(day,RecordedTime,@selectedDate)=0 and t.CurrNo!=c.maxno
    order by t.RecordedTime 
    )
    select t.CustName,t.Country,t.RecordedTime,cnt
    ,case when t.CurrNo=1 then 'ADD' else 'CHANGE' End as Audit
    ,case when t.CurrNo=1 then 'NEW' when t.CurrNo=c.maxno then 'CURRENT' else 'BEFORE' end History
     from #Test t join cte c on c.CustName =t.CustName
    where datediff(day,RecordedTime,@selectedDate)=0 and (t.CurrNo=c.maxno or t.CurrNo=1)
    union 
    select top 1 t.CustName,t.Country,t.RecordedTime,cnt
    ,'CHANGE' Audit
    ,'BEFORE' History
     from #Test t join cte c on c.CustName =t.CustName
    where datediff(day,RecordedTime,@selectedDate)=0 and t.CurrNo=1 and c.cnt>1
    union 
    select top 1 t.CustName,t.Country,t.RecordedTime,cnt
    ,'CHANGE' Audit
    ,'BEFORE' History
     from cte2 t order by RecordedTime
    
    drop table #Test
    

    There is a nice point by "Ronen Ariely". And below is the updated query with 2 times table scan instead of 8.

    with cte as
    (
    select CustName,max(CurrNo) maxno,count(1) cnt
    from #Test where datediff(day,RecordedTime,@selectedDate)=0 
    group by CustName
    ),cte2 as (
    select * from #Test where CustName in 
    (
    select distinct custname from cte
    )
    and datediff(day,RecordedTime,@selectedDate)>=0
    ),cte3 as (
    select top 1 t.*,cnt
     from cte2 t join cte c on c.CustName =t.CustName
    where datediff(day,RecordedTime,@selectedDate)>0 and t.CurrNo!=c.maxno
    order by t.RecordedTime  desc
    union select top 1 t.*,cnt
     from cte2 t join cte c on c.CustName =t.CustName
    where datediff(day,RecordedTime,@selectedDate)=0 and t.CurrNo!=c.maxno
    order by t.RecordedTime 
    )
    select t.CustName,t.Country,t.RecordedTime
    ,case when t.CurrNo=1 then 'ADD' else 'CHANGE' End as Audit
    ,case when t.CurrNo=1 then 'NEW' when t.CurrNo=c.maxno then 'CURRENT' else 'BEFORE' end History
     from cte2 t join cte c on c.CustName =t.CustName
    where datediff(day,RecordedTime,@selectedDate)=0 and (t.CurrNo=c.maxno or t.CurrNo=1)
    union 
    select top 1 t.CustName,t.Country,t.RecordedTime
    ,'CHANGE' Audit
    ,'BEFORE' History
     from cte2 t join cte c on c.CustName =t.CustName
    where datediff(day,RecordedTime,@selectedDate)=0 and t.CurrNo=1 and c.cnt>1
    union 
    select top 1 t.CustName,t.Country,t.RecordedTime
    ,'CHANGE' Audit
    ,'BEFORE' History
     from cte3 t order by RecordedTime
    

提交回复
热议问题