Home > Software design >  Get orders for each customer after a specific date for each customer
Get orders for each customer after a specific date for each customer

Time:06-01

Forgive me if I word this poorly. And sorry if it has already been asked, but I was not able to find an answer here.

I'm using Snowflake to try and do the below.

Basically, I'm trying to do a piece of work to find out how many times a customer as placed an order after a specific date for each customer.

Scenario: We want to see if customers continue to shop with us after they have been short-shipped (received 1 or more items less than they ordered).

So for example:
customer 1 places an order on 01/01/2020 and this was a short-shipment.
they then go on to place an order 06/06/2020 and 02/02/2021.
so this customer has a total of 2 additional orders since they were short-shipped on 01/01/2020.\

customer 2 places an order on 02/03/2020 and this was short-shipped.
customer 2 has not since placed an order, so they will have 0 additional orders.

Data available:

cust_id ord_id order_date
1 0123 01/01/2020
1 0456 06/06/2020
1 0789 02/02/2021
2 1011 01/01/2020

Desired output:

cust_id number_of_orders
1 2
2 0

CodePudding user response:

So using a boosted version of your data:

with data_cte( cust_id, ord_id, order_date, short_order_flg) as (
    select * from values
    (1, '1', '2018-06-06'::date, false),
    (1, '2', '2019-01-01'::date, true), 
    (1, '3', '2019-06-06'::date, false),
    (1, '4', '2019-12-02'::date, false),
    (1, '5', '2020-01-01'::date, true), 
    (1, '6', '2020-06-06'::date, false),
    (1, '7', '2021-02-02'::date, false),
    (2, '8', '2020-01-01'::date, true)
)

which shows a "valid" purchase, multiple "short ships" and how to batch them

SELECT 
    cust_id, 
    min(order_date) as short_date, 
    count(*) -1 as follow_count
FROM (
    select 
        cust_id
        ,order_date
        ,CONDITIONAL_TRUE_EVENT(short_order_flg) over(partition by cust_id order by order_date ) as edge
    from data_cte
)
where edge > 0
group by 1, edge
order by 1,2;

gives:

CUST_ID SHORT_DATE FOLLOW_COUNT
1 2019-01-01 2
1 2020-01-01 2
2 2020-01-01 0

The key things to note, CONDITIONAL_TRUE_EVENT increases each time the event happen, which gives cust_id,edge value as batch key, and if the event has not happened those lines are zero, thus the WHERE filter.

The last things is given we have atleast one count for the start of "post short" batch, we need to subtract one from the count.

CodePudding user response:

Try this

with CTE as (
select 1 as cust_id, '0123' as ord_id, '2020-01-01'::date as order_date, 1 as short_order_flg union all 
select 1 as cust_id, '0456' as ord_id, '2020-06-06'::date as order_date, 0 as short_order_flg union all 
select 1 as cust_id, '0789' as ord_id, '2021-02-02'::date as order_date, 0 as short_order_flg union all 
select 2 as cust_id, '1011' as ord_id, '2020-01-01'::date as order_date, 1 as short_order_flg
),
following_orders as (
select cust_id, short_order_flg, count(ord_id) over (partition by cust_id order by order_date rows between current row and unbounded following) - 1 as number_of_orders
from cte
order by cust_id, order_date
)
select cust_id, number_of_orders
from following_orders
where short_order_flg = 1
;

I added column short_order_flg to indicate which record represents the short order. Then I used window function count(ord_id) over(...) to calculate the number of orders following each order, subtracting 1 to exclude the current record itself. Finally, I applied a filter to select only the short order records.

  • Related