skip to Main Content

I have the following table:

CREATE TABLE table_one( person varchar(55), date_value date, proj varchar(2), value int, time varchar(2 ); 

INSERT INTO table_one VALUES 

('A1',2020-10-01'W',10,'T1')
('A1',2020-10-01'A',5,'T2')
('A1',2020-10-01'P',6,'T3')
('A1',2020-10-01'A',9,'T4')
('A1',2020-10-01'P',11,'T5')
('A1',2020-10-01'A',4,'T6')
('A1',2020-10-01'P',2,'T7')
('A1',2020-10-01'A',1,'T8')
('A1',2020-10-01'P',10,'T9')
('A1',2020-10-01'A',8,'T10')

I want an SQL query which creates a new column ‘new_value’. The following are the conditions to fill that new column:

Case-1 When proj = A and next row proj = P , then take value of Proj=a in new_value column corresponding to proj=p.

For example, for row 2 the proj value is A and row 3 proj value is P. So the new column value correspoding to row-3 should be 5.

Case-2 When last row = A and the first row is W, then allocate value of last row in new_value column.

For example, row-10 has proj value A and row-1 has proj value W. So the new_value column correspoding to row-1 should be 8.

CASE-3 New_val should be NULL when proj = A.

Refer to the following picture for visual help

enter image description here

the above query needs to be aggregated at person,date_value column.

2

Answers


  1. SELECT person,date_value,proj,value,
    lag(proj) ignore nulls over (PARTITION BY person order by row_num) last_proj,
    lag(value) ignore nulls over (PARTITION BY person order by row_num) last_proj_value,
    last_value(proj) ignore nulls over (PARTITION BY person order by row_num) person_last_proj,
    first_value(proj) ignore nulls over (PARTITION BY person order by row_num) person_first_proj,
    last_value(value) ignore nulls over (PARTITION BY person order by row_num) person_last_proj_value,
    CASE 
      WHEN proj='P' AND last_proj = 'A' THEN last_proj_value --Case_1
      WHEN person_last_proj = 'A' AND person_first_proj = 'W' AND row_num = 1 THEN person_last_proj_value --case_2
      WHEN proj='A' THEN NULL --CASE_3
      ELSE NULL
    END AS New_value
    FROM 
    (SELECT person,date_value,proj,value,row_number() over (partition by person order by date_value) as row_num
    FROM table_one);
    
    Login or Signup to reply.
  2. I changed the sample data TIME column from varchar to int. The reason is that strings won’t sort right. In string comparisons, ’10’ < ‘9’.

    CREATE TABLE TABLE_ONE( person varchar(55), date_value date, proj varchar(2), value int, time int);

    INSERT INTO TABLE_ONE VALUES 
    ('A1','2020-10-01','W',10,1),
    ('A1','2020-10-01','A',5,2),
    ('A1','2020-10-01','P',6,3),
    ('A1','2020-10-01','A',9,4),
    ('A1','2020-10-01','P',11,5),
    ('A1','2020-10-01','A',4,6),
    ('A1','2020-10-01','P',2,7),
    ('A1','2020-10-01','A',1,8),
    ('A1','2020-10-01','P',10,9),
    ('A1','2020-10-01','A',8,10)
    ;
    
    
    select *, 
            case
                when PROJ = 'P' and lag(PROJ) over (partition by PERSON order by DATE_VALUE, TIME) = 'A' then 
                    lag(VALUE) over (partition by PERSON order by DATE_VALUE, TIME)
                when row_number() over (partition by PERSON order by DATE_VALUE, TIME) = 1 and
                     last_value(PROJ) over (partition by PERSON order by DATE_VALUE, TIME) = 'A' then
                     last_value(VALUE) over (partition by PERSON order by DATE_VALUE, TIME)
            end as NEW_VALUE
    from TABLE_ONE order by DATE_VALUE, TIME;
    
    PERSON DATE_VALUE PROJ VALUE TIME NEW_VALUE
    A1 2020-10-01 00:00:00 W 10 1 8
    A1 2020-10-01 00:00:00 A 5 2 null
    A1 2020-10-01 00:00:00 P 6 3 5
    A1 2020-10-01 00:00:00 A 9 4 null
    A1 2020-10-01 00:00:00 P 11 5 9
    A1 2020-10-01 00:00:00 A 4 6 null
    A1 2020-10-01 00:00:00 P 2 7 4
    A1 2020-10-01 00:00:00 A 1 8 null
    A1 2020-10-01 00:00:00 P 10 9 1
    A1 2020-10-01 00:00:00 A 8 10 null
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search