Home > Back-end >  Joining two tables where date in second table should be first date after date in first table i.e ear
Joining two tables where date in second table should be first date after date in first table i.e ear

Time:10-24

Problem statement description :- I have two tables - table1 and table2 . table1 contains data of quantity buy of id=7 and table2 contain data of quantity sold of same id=7. Both table1 and table2 is sorted according to date i.e from oldest to latest date and every time only 1 quantity is buy or sold.

table1:

table1
date_buy id qty_buy rolling_sum_qty_buy
30-07-2019 7 1 1
20-10-2019 7 1 2
17-01-2020 7 1 3
15-02-2020 7 1 4
15-02-2020 7 1 5
15-02-2020 7 1 6
14-07-2021 7 1 7
19-09-2021 7 1 8
25-12-2021 7 1 9
30-12-2021 7 1 10
10-02-2022 7 1 11
15-03-2022 7 1 12
15-03-2022 7 1 13
14-06-2022 7 1 14

table2:-

table2
date_sold id qty_sold rolling_sum_qty_sold
01-08-2019 7 1 1
15-09-2019 7 1 2
27-12-2019 7 1 3
01-02-2020 7 1 4
12-02-2020 7 1 5
25-07-2021 7 1 6
25-07-2021 7 1 7
28-08-2021 7 1 8
10-09-2021 7 1 9
12-09-2021 7 1 10
25-04-2022 7 1 11

-- SQL scrtpt of table1:

CREATE TABLE IF NOT EXISTS table1 (
    `date_buy` DATETIME,
    `id` INT,
    `qty_buy` INT,
    `rolling_sum_qty_buy` INT
);
INSERT INTO table1 VALUES
    ('2019-07-30 00:00:00',7,1,1),
    ('2019-10-20 00:00:00',7,1,2),
    ('2020-01-17 00:00:00',7,1,3),
    ('2020-02-15 00:00:00',7,1,4),
    ('2020-02-15 00:00:00',7,1,5),
    ('2020-02-15 00:00:00',7,1,6),
    ('2021-07-14 00:00:00',7,1,7),
    ('2021-09-19 00:00:00',7,1,8),
    ('2021-12-25 00:00:00',7,1,9),
    ('2021-12-30 00:00:00',7,1,10),
    ('2022-02-10 00:00:00',7,1,11),
    ('2022-03-15 00:00:00',7,1,12),
    ('2022-03-15 00:00:00',7,1,13),
    ('2022-06-14 00:00:00',7,1,14);

-- sql script of table2:

CREATE TABLE IF NOT EXISTS table2 (
    `date_sold` DATETIME,
    `id` INT,
    `qty_sold` INT,
    `rolling_sum_qty_sold` INT
);
INSERT INTO table2 VALUES
    ('2019-08-01 00:00:00',7,1,1),
    ('2019-09-15 00:00:00',7,1,2),
    ('2019-12-27 00:00:00',7,1,3),
    ('2020-02-01 00:00:00',7,1,4),
    ('2020-02-12 00:00:00',7,1,5),
    ('2021-07-25 00:00:00',7,1,6),
    ('2021-07-25 00:00:00',7,1,7),
    ('2021-08-28 00:00:00',7,1,8),
    ('2021-09-10 00:00:00',7,1,9),
    ('2021-09-12 00:00:00',7,1,10),
    ('2022-04-25 00:00:00',7,1,11);

-- Now, i want to join this two table on two condition

  1. for every date i.e date_buy column in table1 i should get output where date i.e date_sold is greater than date_buy and i want first date i.e. date_sold which is greater than that particular date i.e date_buy.

  2. i also want those rows from table1 in my output which does not get joined with table2 so that i can easily find out the remaining quantity because in table1 i have quantity buy and after joining with table2 i will get quantity sold, so the cases where i get null values then in that case i can assume that that much quantity is remaining.

--My output:- Earlier when there was no date issue then i was simply using left join to join table1 and table2 on rolling sum condition and where there was null cases i was taking sum of qty to get remaining qty but right now i have that condition too so i cant use rolling_sum_cond column directly in join condition.

-- query which i was using and output which i was getting earlier

select * from table1
left join table2 
on table1.rolling_sum_qty_buy=table2.rolling_sum_qty_sold
date_buy id qty_buy rolling_sum_qty_buy date_sold id-2 qty_sold rolling_sum_qty_sold
30-07-2019 7 1 1 01-08-2019 7 1 1
20-10-2019 7 1 2 15-09-2019 7 1 2
17-01-2020 7 1 3 27-12-2019 7 1 3
15-02-2020 7 1 4 01-02-2020 7 1 4
15-02-2020 7 1 5 12-02-2020 7 1 5
15-02-2020 7 1 6 25-07-2021 7 1 6
14-07-2021 7 1 7 25-07-2021 7 1 7
19-09-2021 7 1 8 28-08-2021 7 1 8
25-12-2021 7 1 9 10-09-2021 7 1 9
30-12-2021 7 1 10 12-09-2021 7 1 10
10-02-2022 7 1 11 25-04-2022 7 1 11
15-03-2022 7 1 12 NULL NULL NULL NULL
15-03-2022 7 1 13 NULL NULL NULL NULL
14-06-2022 7 1 14 NULL NULL NULL NULL

and to find out remaining quantity , i was using null condition query:-

 with cte as 
(
select * from table1
left join table2 
on table1.rolling_sum_qty_buy=table2.rolling_sum_qty_sold
)
select sum(qty_buy) as remaining_qty 
from cte
where cte.date_sold is null
 
remaining_qty
3

-- my expectation now i have to use date condition also to get the output

-- Expected Output

date_buy id qty_buy rolling_sum_qty_buy date_sold id qty_sold rolling_sum_qty_sold
30-07-2019 7 1 1 01-08-2019 7 1 1
20-10-2019 7 1 2 27-12-2019 7 1 3
17-01-2020 7 1 3 01-02-2020 7 1 4
15-02-2020 7 1 4 25-07-2021 7 1 6
15-02-2020 7 1 5 25-07-2021 7 1 7
15-02-2020 7 1 6 28-08-2021 7 1 8
14-07-2021 7 1 7 10-09-2021 7 1 9
19-09-2021 7 1 8 25-04-2022 7 1 11
25-12-2021 7 1 9 NULL NULL NULL NULL
30-12-2021 7 1 10 NULL NULL NULL NULL
10-02-2022 7 1 11 NULL NULL NULL NULL
15-03-2022 7 1 12 NULL NULL NULL NULL
15-03-2022 7 1 13 NULL NULL NULL NULL
14-06-2022 7 1 14 NULL NULL NULL NULL

-- Please help me to get the following output. Any help would be appreciated. I am using postgresql.

CodePudding user response:

That was a challenging one.

with recursive cte as
(
  select   t2.date_sold
          ,t2.rolling_sum_qty_sold
          ,true as is_match
          ,1 as last_rolling_sum_qty_buy                           
  from     t2 join t on t2.rolling_sum_qty_sold = t.rolling_sum_qty_buy
  where    t2.rolling_sum_qty_sold = 1 
        
   
  union all 
  
  select t2.date_sold
        ,t2.rolling_sum_qty_sold 
        ,t2.date_sold >= t.date_buy
        ,cte.last_rolling_sum_qty_buy   case when t2.date_sold >= t.date_buy then 1 else 0 end
  from   t2 
         join cte on cte.rolling_sum_qty_sold   1 = t2.rolling_sum_qty_sold
         join t   on t.rolling_sum_qty_buy = cte.last_rolling_sum_qty_buy   1
          
)

select  t.date_buy  
       ,t.id    
       ,t.qty_buy   
       ,t.rolling_sum_qty_buy   
       ,cte.date_sold   
       ,cte.rolling_sum_qty_sold
from    t left join cte on cte.last_rolling_sum_qty_buy = t.rolling_sum_qty_buy and is_match
date_buy id qty_buy rolling_sum_qty_buy date_sold rolling_sum_qty_sold
2019-07-30 7 1 1 2019-08-01 1
2019-10-20 7 1 2 2019-12-27 3
2020-01-17 7 1 3 2020-02-01 4
2020-02-15 7 1 4 2021-07-25 6
2020-02-15 7 1 5 2021-07-25 7
2020-02-15 7 1 6 2021-08-28 8
2021-07-14 7 1 7 2021-09-10 9
2021-09-19 7 1 8 2022-04-25 11
2021-12-25 7 1 9 null null
2021-12-30 7 1 10 null null
2022-02-10 7 1 11 null null
2022-03-15 7 1 12 null null
2022-03-15 7 1 13 null null
2022-06-14 7 1 14 null null

Fiddle

  • Related