基于购买日期的每日消费增量

时间:2018-10-30 06:45:33

标签: mysql sql tableau

我需要制作一个(Tableau)每日图表,以相对于前一天的消费动态进行描述,这些客户将消费增加,消费减少和总体净变化的客户分组。示例如下。

样本的计算逻辑:对于每个客户的每一天,计算该客户与前一天的差额,将大于0的那些相加,将小于0的那些相加,求和。 enter image description here

样本是从相对较小的数据集中手动制作的。 实际表有超过200万行,并且不一致,因为客户在不同的日期开始购买,可能会跳过各个时期不进行任何购买的时间。 初始表结构是这样的:

client_id   date    sales
    1   2018-09-01  4
    1   2018-09-02  5
    1   2018-09-04  3
    2   2018-09-1   2
    2   2018-09-2   2

虽然计算每个日期的表差异很简单,但是计算纯增长和纯客户流失却很困难,因为对于所有客户而言,日期行不是连续的。 我想从数据存储中加载初始数据集时将delta_to_previous列添加到每一行,例如:

WITH orders AS (
    SELECT client_id,
           date,
           SUM(sales) as sales
    FROM dwh_orders
    GROUP BY client_id, date
)
SELECT
    client_id, 
    date, 
    sales,
    LAG(sales, 1) OVER (
        PARTITION BY client_id
        ORDER BY date
    ) as prev_date_order_value,
    sales - LAG(sales, 1) OVER (
        PARTITION BY client_id
        ORDER BY date
    ) as prev_date_order_delta
FROM 
    orders;

然后对于每个日期,我只能显示正值,负值和总计的总和。

问题,这种方法将在下一个购买日期显示消费变化,并且如果客户在3月1日购买了5件商品,然后在5月1日购买了5件商品,那么他将完全没有变化。它应该做的是在3月2日显示-5,在5月1日显示+5。

我对采用最佳方法感到有些困惑。通用解决方案也可能需要进行一些审查。

如果有人处理类似的问题,我真的可以使用您的建议。 如果您有使用sql的经验,我可以就如何将初始数据集(请参见上面的示例)转换为

client_id   date    sales delta
    1   2018-09-01  4   0
    1   2018-09-02  5   1
    1   2018-09-03  0   -5
    1   2018-09-04  3   3
    2   2018-09-1   2   0
    2   2018-09-2   2   0

如果您对Tableau有所了解,我可以使用其工具来帮助构建这样的图形。

1 个答案:

答案 0 :(得分:0)

with cdates as (
      select client_id, min(date) as dte, max(date) as maxd
      from dwh_orders
      group by client_id
      union all
      select client_id, dateadd(day, 1, dte), maxd
      from cdates
      where dte < maxd
     ),
     cd as (
      select client_id, date, sum(sales) as sales
      from dwh_orders
      group by client_id, date
    )
select cdates.client_id, cdates.date,
       coalesce(sales, 0) as sales,
       (coalesce(sales, 0) -
        lag(coalesce(sales, 0)) over (partition by cdates.client_id order by cdates.date
       ) as delta
from cdates left join
     cd
     on cdates.client_id = cd.client_id and
        cdates.date = cd.date
option (maxrecursion 0);