Share via

help with sql script

leo dec 41 Reputation points
2021-06-04T09:44:22.793+00:00

Hi

I need help to write sql script to get the tab1_result

sample data is in tab1 and result needed in tab1_result

with tab1 as
(
select 101 as id,  'abc' as area,'2021-01-07' as strt_dt,'2021-01-07' as end_dt, '2021-01-07' as daily_dt
union
select 101 as id, 'abc' as area, '2021-01-07' as strt_dt, '2021-01-08' as end_dt, '2021-01-07' as daily_dt
union
select 101 as id, 'mno' as area,'2021-01-08' as strt_dt,'2021-01-15' as end_dt, '2021-01-08' as daily_dt
union
select 101 as id,  NULL as area,NULL as strt_dt,NULL as end_dt, '2021-01-09' as daily_dt
union
select 101 as id,  NULL as area,NULL as strt_dt,NULL as end_dt, '2021-01-10' as daily_dt
union
select 101 as id,  NULL as area,NULL as strt_dt,NULL as end_dt, '2021-01-11' as daily_dt
union
select 101 as id,  NULL as area,NULL as strt_dt,NULL as end_dt, '2021-01-12' as daily_dt
union
select 101 as id,  NULL as area,NULL as strt_dt,NULL as end_dt, '2021-01-13' as daily_dt
union
select 101 as id,  NULL as area,NULL as strt_dt,NULL as end_dt, '2021-01-14' as daily_dt
union
select 101 as id,  'tt' as area,'2021-01-15' as strt_dt, '2021-01-17' as end_dt, '2021-01-15' as daily_dt
union
select 101 as id,  NULL as area,NULL as strt_dt,NULL as end_dt, '2021-01-16' as daily_dt
union
select 101 as id,  NULL as area,NULL as strt_dt,NULL as end_dt, '2021-01-17' as daily_dt
)select * from tab1




 with tab1_result as
(
select 101 as id,  'abc' as area,'2021-01-07' as strt_dt,'2021-01-07' as end_dt, '2021-01-07' as daily_dt
union
select 101 as id, 'abc' as area, '2021-01-07' as strt_dt, '2021-01-08' as end_dt, '2021-01-07' as daily_dt
union
select 101 as id, 'abc' as area, '2021-01-08' as strt_dt, '2021-01-08' as end_dt, '2021-01-08' as daily_dt
union
select 101 as id, 'mno' as area,'2021-01-08' as strt_dt,'2021-01-15' as end_dt, '2021-01-08' as daily_dt
union
select 101 as id,  'mno' as area,NULL as strt_dt,NULL as end_dt, '2021-01-09' as daily_dt
union
select 101 as id,  'mno' as area,NULL as strt_dt,NULL as end_dt, '2021-01-10' as daily_dt
union
select 101 as id,  'mno' as area,NULL as strt_dt,NULL as end_dt, '2021-01-11' as daily_dt
union
select 101 as id,  'mno' as area,NULL as strt_dt,NULL as end_dt, '2021-01-12' as daily_dt
union
select 101 as id,  'mno' as area,NULL as strt_dt,NULL as end_dt, '2021-01-13' as daily_dt
union
select 101 as id,  'mno' as area,NULL as strt_dt,NULL as end_dt, '2021-01-14' as daily_dt
union
select 101 as id,  'mno' as area,NULL as strt_dt,NULL as end_dt, '2021-01-15' as daily_dt
union
select 101 as id,  'tt' as area,'2021-01-15' as strt_dt, '2021-01-17' as end_dt, '2021-01-15' as daily_dt
union
select 101 as id,  'tt' as area,NULL as strt_dt,NULL as end_dt, '2021-01-16' as daily_dt
union
select 101 as id,  'tt' as area,NULL as strt_dt,NULL as end_dt, '2021-01-17' as daily_dt
)select * from tab1_result
Developer technologies | Transact-SQL
Developer technologies | Transact-SQL

A Microsoft extension to the ANSI SQL language that includes procedural programming, local variables, and various support functions.


2 answers

Sort by: Most helpful
  1. EchoLiu-MSFT 14,626 Reputation points
    2021-06-07T08:11:08.193+00:00

    Please also check:

     CREATE TABLE #test(  
      id          INT,  
      area     VARCHAR(100),  
      strt_dt     DATE,  
      end_dt     DATE,  
      daily_dt    DATE  
     )  
     GO  
          
     INSERT #test(id,area,strt_dt,end_dt,daily_dt)  
      select 101 as id,  'abc' as area,'2021-01-07' as strt_dt,'2021-01-07' as end_dt, '2021-01-07' as daily_dt  
      union  
      select 101 as id, 'abc' as area, '2021-01-07' as strt_dt, '2021-01-08' as end_dt, '2021-01-07' as daily_dt  
      union  
      select 101 as id, 'mno' as area,'2021-01-08' as strt_dt,'2021-01-15' as end_dt, '2021-01-08' as daily_dt  
      union  
      select 101 as id,  NULL as area,NULL as strt_dt,NULL as end_dt, '2021-01-09' as daily_dt  
      union  
      select 101 as id,  NULL as area,NULL as strt_dt,NULL as end_dt, '2021-01-10' as daily_dt  
      union  
      select 101 as id,  NULL as area,NULL as strt_dt,NULL as end_dt, '2021-01-11' as daily_dt  
      union  
      select 101 as id,  NULL as area,NULL as strt_dt,NULL as end_dt, '2021-01-12' as daily_dt  
      union  
      select 101 as id,  NULL as area,NULL as strt_dt,NULL as end_dt, '2021-01-13' as daily_dt  
      union  
      select 101 as id,  NULL as area,NULL as strt_dt,NULL as end_dt, '2021-01-14' as daily_dt  
      union  
      select 101 as id,  'tt' as area,'2021-01-15' as strt_dt, '2021-01-17' as end_dt, '2021-01-15' as daily_dt  
      union  
      select 101 as id,  NULL as area,NULL as strt_dt,NULL as end_dt, '2021-01-16' as daily_dt  
      union  
      select 101 as id,  NULL as area,NULL as strt_dt,NULL as end_dt, '2021-01-17' as daily_dt  
     GO  
          
     SELECT * FROM #test  
      
    ;WITH cte  
    as(SELECT id,area,MAX(val) ma,MIN(val) mi FROM   
    (SELECT * FROM #test  
    unpivot (val for dt in (strt_dt,end_dt,daily_dt)) as t  
    WHERE area is not null) u  
    GROUP BY id,area)  
      
    SELECT t.id,c.area,CASE WHEN t.area is not null and t.area<>c.area   
    and c.area <>'abc' and t.daily_dt<>'2021-01-08'  
    THEN NULL   
    WHEN c.area ='abc' and t.daily_dt='2021-01-08'  
    THEN t.daily_dt  
    ELSE t.strt_dt END strt_dt,  
    CASE WHEN t.area is not null and t.area<>c.area   
    and c.area <>'abc' and t.daily_dt<>'2021-01-08'  
    THEN NULL   
    WHEN c.area ='abc' and t.daily_dt='2021-01-08'  
    THEN t.daily_dt  
    ELSE t.end_dt END end_dt,t.daily_dt  
    FROM #test t   
    LEFT JOIN cte c ON c.id=t.id AND c.area=t.area OR t.daily_dt BETWEEN mi AND ma  
    ORDER BY c.area,t.daily_dt  
    

    Output:
    102925-image.png

    If you have any question, please feel free to let me know.

    Regards
    Echo


    If the answer is helpful, please click "Accept Answer" and upvote it.

    Was this answer helpful?

    0 comments No comments

  2. Ronen Ariely 15,221 Reputation points
    2021-06-05T07:46:26.06+00:00

    Good day,

    your description is not clear to me but I have a guess of what you meant or need and it returns the expected result. THIS IS TOTALLY BASED ON A GUESS.

    As much as I see you have multiple rows with null in the column area, and you ignore these. Next you simply need to fill the gaps according to the stat and end data (strt_dt,end_dt)

    Step one: We need table to work with and not a running query, and we need an accessory calendar table

    CREATE TABLE T(  
     id          INT,  
     area     VARCHAR(100),  
     strt_dt     DATE,  
     end_dt     DATE,  
     daily_dt    DATE  
    )  
    GO  
      
    INSERT T(id,area,strt_dt,end_dt,daily_dt)  
     select 101 as id,  'abc' as area,'2021-01-07' as strt_dt,'2021-01-07' as end_dt, '2021-01-07' as daily_dt  
     union  
     select 101 as id, 'abc' as area, '2021-01-07' as strt_dt, '2021-01-08' as end_dt, '2021-01-07' as daily_dt  
     union  
     select 101 as id, 'mno' as area,'2021-01-08' as strt_dt,'2021-01-15' as end_dt, '2021-01-08' as daily_dt  
     union  
     select 101 as id,  NULL as area,NULL as strt_dt,NULL as end_dt, '2021-01-09' as daily_dt  
     union  
     select 101 as id,  NULL as area,NULL as strt_dt,NULL as end_dt, '2021-01-10' as daily_dt  
     union  
     select 101 as id,  NULL as area,NULL as strt_dt,NULL as end_dt, '2021-01-11' as daily_dt  
     union  
     select 101 as id,  NULL as area,NULL as strt_dt,NULL as end_dt, '2021-01-12' as daily_dt  
     union  
     select 101 as id,  NULL as area,NULL as strt_dt,NULL as end_dt, '2021-01-13' as daily_dt  
     union  
     select 101 as id,  NULL as area,NULL as strt_dt,NULL as end_dt, '2021-01-14' as daily_dt  
     union  
     select 101 as id,  'tt' as area,'2021-01-15' as strt_dt, '2021-01-17' as end_dt, '2021-01-15' as daily_dt  
     union  
     select 101 as id,  NULL as area,NULL as strt_dt,NULL as end_dt, '2021-01-16' as daily_dt  
     union  
     select 101 as id,  NULL as area,NULL as strt_dt,NULL as end_dt, '2021-01-17' as daily_dt  
    GO  
      
    SELECT * FROM T  
    GO  
    

    For the sake of the answer we will need an accessory calendar table - a table with all the dates.

    Note! Do not forget to create a table which fit production including indexes. I only present the base solution with simple Heap table.

    CREATE TABLE Dates (TheData DATE)  
    INSERT Dates   
     SELECT TOP 1000  
     DATEADD(  
     DAY,   
     ROW_NUMBER() OVER (ORDER BY (select null)),   
     CONVERT (DATE, '2021-01-01', 120)  
     )  
     FROM sys.all_objects  
    GO  
    

    Step 2: Now we can (guess) solve the the issue

    Basicaly, I take the rows where the area is not a null and add the missing rows

    select id, area,   
     strt_dt = CASE WHEN daily_dt = TheData THEN strt_dt ELSE NULL END,  
     end_dt = CASE WHEN daily_dt = TheData THEN end_dt ELSE NULL END,  
     D.TheData  
    from T  
    LEFT JOIN Dates D ON T.strt_dt <= D.TheData and T.end_dt >= D.TheData   
    where T.area is not null  
    order by TheData,daily_dt,strt_dt,end_dt  
    GO  
    

    102643-image.png

    Is this fits your needs?

    Was this answer helpful?

    0 comments No comments

Your answer

Answers can be marked as 'Accepted' by the question author and 'Recommended' by moderators, which helps users know the answer solved the author's problem.