sam
sam

Reputation: 251

Advanced SQL with window function

I have Table a(Dimension table) and Table B(Fact table) stores transaction shopper history.

Table a : shopped id(surrogate key) created for unique combination(any of column 2,colum3,column4 repeated it will have same shopper id)

Table b is transaction data. enter image description here

I am trying to identify New customers and repeated customers for each week, expected output is below.

enter image description here

I am thinking following SQL Statement

Select COUNT(*) OVER (PARTITION BY shopperid,weekdate) as total_new_shopperid for Repeated customer, for Identifying new customer(ie unique) in same join condition, I am stuck on window function..

thanks,

Sam

Upvotes: 0

Views: 259

Answers (2)

Gordon Linoff
Gordon Linoff

Reputation: 1269763

Tejash's answer is fine (and I'm upvoting it).

However, Oracle is quite efficient with aggregation, so two levels of aggregation might have better performance (depending on the data):

select week_date,
       sum(case when min_week_date = week_date then 1 else 0 end) as new_shoppers,
       sum(case when min_week_date = week_date then amount else 0 end) as new_shopper_amount,
       sum(case when min_week_date > week_date then 1 else 0 end) as returning_shoppers,
       sum(case when min_week_date > week_date then amount else 0 end) as returning_amount
from (select shopper_id, week_date,
             sum(amount) as amount,
             min(week_date) over (partition by shopper_id) as min_week_date
      from t
      group by shopper_id, week_date
     ) sw
group by week_date
order by week_date;

Note: If this has better performance, it is probably due to the elimination of count(distinct).

Upvotes: 0

Popeye
Popeye

Reputation: 35900

You can use the DENSE_RANK analytical function along with aggregate function as follows:

SELECT WEEK_DATE, 
       COUNT(DISTINCT CASE WHEN DR = 1 THEN SHOPPER_ID END) AS TOTAL_NEW_CUSTOMER,
       SUM(CASE WHEN DR = 1 THEN AMOUNT END) AS TOTAL_NEW_CUSTOMER_AMT,
       COUNT(DISTINCT CASE WHEN DR > 1 THEN SHOPPER_ID END) AS TOTAL_REPEATED_CUSTOMER,
       SUM(CASE WHEN DR > 1 THEN AMOUNT END) AS TOTAL_REPEATED_CUSTOMER_AMT 
  FROM
      (
        select T.*, 
               DENSE_RANK() OVER (PARTITION BY SHOPPER_ID ORDER BY WEEK_DATE) AS DR
          FROM YOUR_TABLE T);
GROUP BY WEEK_DATE;

Cheers!!

Upvotes: 1

Related Questions