Reputation: 1522
I have 2 tables: orders
and contragents
. Each contragent might have many orders. Each order has an order_date
. I want to get a first order date for each contragent, but with a caveat: if there was a gap between orders more than 180 days, I need to "forget" those before the gap (and thus the first order after the gap is considered "the first".
For this, I've implement a following statement:
with o1 as (
select order_date, lag(order_date) over(order by order_date ASC) as prev_order_date
from orders o
where o.contragent_code = :code
order by order_date desc)
select o1.date_debts from o1
where extract(day from o1.order_date-o1.prev_order_date)>=180 or o1.prev_order_date is null
order by order_date desc
limit 1
this results in a single value being returned for a contragent with code code
, which is what I need.
But I cannot figure out how to run a select that would return this date for every contragent in a table!
The only way I was able to do it was using a CREATE FUNCTION
, but I will be unable to do it on production, so.. any advice is highly appreciated!
Upvotes: 2
Views: 44
Reputation: 2017
You want to add partition by
, which is kinda like group by
for over
.
with o1 as (
select order_date, lag(order_date) over(partition by contragent_code order by order_date ASC) as prev_order_date
from orders o
order by order_date desc)
select o1.date_debts from o1
where extract(day from o1.order_date-o1.prev_order_date)>=180 or o1.prev_order_date is null
order by order_date desc
Now lag
looks for the previous order_date of rows with same contragent_code.
UPDATE: at the end, it appears that that was not exactly enough. This is the final statement:
with s as (
select o.contragent_code, o.order_date,
case
when
extract(day from order_date-lag(order_date) over(partition by contragent_code order by order_date asc))>=180
then o.order_date else null
end as date_with_gap
from orders o
) select contragent_code, coalesce(max(date_with_gap), min(order_date)) from s
group by contragent_code
Upvotes: 1