具有窗口功能的高级SQL

时间:2020-03-06 04:24:54

标签: sql oracle window-functions

我有表a(维度表)和表B(事实表)存储交易购物者的历史记录。

表a:为唯一组合(重复的第2列,第3列,第4列中的任何一个将具有相同的购物者ID)创建的购物ID(代理键)

表b是交易数据。 enter image description here

我正在尝试确定每周的新客户和回头客,预期产出如下。

enter image description here

我正在考虑遵循SQL语句

为回头客选择COUNT(*)OVER(按shopperid,星期日期划分)作为total_new_shopperid, 为了确定在相同加入条件下的新客户(即唯一客户),我被困在窗口功能上。

谢谢

山姆

2 个答案:

答案 0 :(得分:1)

您可以如下使用DENSE_RANK分析函数和聚合函数:

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;

干杯!

答案 1 :(得分:0)

Tejash的回答很好(我对此表示反对)。

但是,Oracle在聚合方面非常有效,因此两个聚合级别可能具有更好的性能(取决于数据):

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;

注意:如果这样做有更好的性能,则可能是由于取消了count(distinct)

相关问题