Mysql 基于购买日期的每日消费增量
我需要制作一个每日图表,描绘前一天的消费动态,由增加消费、减少消费和总体净变化的客户分组。样本如下 样本的计算逻辑:对于每个客户的每一天,计算该客户与前一天的差异,对高于0的进行求和,对低于0的进行求和,对总计进行求和。 样本是从一个相对较小的数据集中手工制作的。 真正的表有超过200万行,而且不太一致,因为客户在不同的日期开始购买,可能会跳过不同的时段,什么也不买。 初始表结构如下所示:Mysql 基于购买日期的每日消费增量,mysql,sql,tableau-api,Mysql,Sql,Tableau Api,我需要制作一个每日图表,描绘前一天的消费动态,由增加消费、减少消费和总体净变化的客户分组。样本如下 样本的计算逻辑:对于每个客户的每一天,计算该客户与前一天的差异,对高于0的进行求和,对低于0的进行求和,对总计进行求和。 样本是从一个相对较小的数据集中手工制作的。 真正的表有超过200万行,而且不太一致,因为客户在不同的日期开始购买,可能会跳过不同的时段,什么也不买。 初始表结构如下所示: client_id date sales 1 2018-09-01 4
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稍有了解,我可以使用Tableau的工具帮助您构建这样的图形。您想每天都看到结果吗?你能总结一下你想要什么吗?不清楚。另外:您使用的是MySQL 8还是更早的版本?@Used_By_已经不是我每天都需要的了,Tableau可以在端点之间建立连续的轴。我确实需要没有旅行的日子,但昨天有。对。我想我不确定最有效的方法是什么。从昨天开始,每天的销售都通过“完全加入销售”的方式加入,但到目前为止,这样计算似乎需要8个小时。可能有一个简单的方法我错过了。
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);