I hope someone can help. Suppose I have this table
sto_id | pro_id | o_date | d_date |
---|---|---|---|
38 | 111 | 2021-04-01 | |
30 | 111 | 2021-04-10 | 2021-04-10 |
30 | 222 | 2021-04-15 | |
30 | 222 | 2021-04-18 | 2021-04-19 |
30 | 333 | 2021-04-20 |
and the result I want to see is
first_sto_id | pro_id | min_o_date | first_d_date |
---|---|---|---|
38 | 111 | 2021-04-01 | |
30 | 222 | 2021-04-15 | 2021-04-19 |
30 | 333 | 2021-04-20 |
so if the sto_id is 30 and d_date is null I want so see the next d_date for this pro_id if available. And if sto_id is not 30 then d_date even if it is null.
I tried this:
select
first_value(sto_id) OVER (PARTITION BY pro_id ORDER BY o_date ASC) as first_sto_id,
pro_id,
min(o_date) OVER (PARTITION BY pro_id ORDER BY o_date ASC) as min_o_date,
case when sto_id='30' then min(d_date) OVER (PARTITION BY pro_id ORDER BY o_date ASC)
else first_value(d_date) OVER (PARTITION BY pro_id ORDER BY o_date ASC) end as first_d_date
from tab1
but I am not getting the result I would need. Here also the fiddle
Any suggestions?? Thanks a lot in advance.
CodePudding user response:
Using arrays:
-- PostgreSQL
SELECT
(ARRAY_AGG(sto_id ORDER BY o_date))[1] AS first_sto_id
,pro_id
,MIN(o_date) AS min_o_date
,CASE WHEN (ARRAY_AGG(sto_id ORDER BY o_date))[1] != '30'
THEN (ARRAY_AGG(d_date ORDER BY o_date))[1]
ELSE (ARRAY_REMOVE(ARRAY_AGG(d_date ORDER BY o_date),NULL))[1]
END
FROM tab1
GROUP BY pro_id
ORDER BY pro_id;
Snowflake version:
SELECT
(ARRAY_AGG(sto_id) WITHIN GROUP(ORDER BY o_date))[0] AS first_sto_id
,pro_id
,MIN(o_date) AS min_o_date
,CASE WHEN (ARRAY_AGG(sto_id) WITHIN GROUP(ORDER BY o_date))[0] != '30'
THEN (ARRAY_AGG(d_date) WITHIN GROUP (ORDER BY o_date))[0]
ELSE (ARRAY_COMPACT(ARRAY_AGG(d_date) WITHIN GROUP(ORDER BY o_date)))[0]
END
FROM tab1
GROUP BY pro_id
ORDER BY pro_id;
Related: Equivalent for Keep in Snowflake