我使用Microsoft SQL Server Management Studio。我正在尝试衡量一个电子商务网站的客户保留率。
对于这个,我需要四个值:customer_id
order_purchase_timestamp
age_by_month
first_purchase
age_by_month
和first_purchase
的值不是在我的数据库里。我想计算一下。
在我的数据库中,我有customer_id
和order_purchase_timestamp
。
first_purchase
应该是order_purchase_timestamp
最早的实例。我只想要月份和年份。
age_by_month
应为first_purchase
与order_purchase_timestamp
之间的月差。
我只想衡量每个月的客户留存率,所以如果同一个月有两次购买,那么不应该被显示。
日期在2016-10-01到2018-09-30之间。应按order_purchase_timestamp
订购
一个例子customer_id下面的方法设计得相对容易理解。还有其他方法(例如,窗口函数)可能会稍微更有效;但这使得它在你当前的SQL技能水平下很容易维护。
请注意,下面的SQL命令是相互构建的(所以答案在最后)。下面是一个数据库<>
它基于一个简单的查询(我们将把它用作子查询),该查询查找每个客户的第一个order_purchase_timestamp。
SELECT customer_id, MIN(order_purchase_timestamp) AS first_purchase_date
FROM orders
GROUP BY customer_id
接下来是DATEDIFF来查找两个日期之间的差。
然后,您可以使用上面的子查询来获取每行的第一个日期-然后查找日期差异,例如,
SELECT orders.customer_id,
orders.order_purchase_timestamp,
first_purchases.first_purchase_date,
DATEDIFF(month, first_purchases.first_purchase_date, orders.order_purchase_timestamp) AS age_by_month
FROM orders
INNER JOIN
(SELECT customer_id, MIN(order_purchase_timestamp) AS first_purchase_date
FROM orders
GROUP BY customer_id
) AS first_purchases ON orders.customer_id = first_purchases.customer_id
- 注意- DATEDIFF有一个'gotcha',得到大多数人,但对你有好处-当比较月份时,它忽略天组件,例如,如果发现月份的差异,1月1日和1月31日之间的月份有0差异。另一方面,1月31日和2月1日之间的1个月将有差异。然而,我认为这实际上是你想要的!
但是,当客户在一个月内进行多次购买时,上面的代码会重复(每次购买都有一行)。相反,我们可以按该月进行分组,然后只记录该月的第一次购买。
一个"直接"的方法是对YEAR(orders.order_purchase_timestamp)和MONTH(orders.order_purchase_timestamp)进行分组。然而,我在下面使用了一个小技巧——使用EOMONTH来查找这个月的最后一天。EOMONTH对该月中的任何日期返回相同的日期;因此,我们可以据此分组。
最后,您可以添加WHERE表达式和ORDER BY来获得您所要求的结果(在两个日期之间)
SELECT orders.customer_id,
MIN(orders.order_purchase_timestamp) AS order_purchase_timestamp,
first_purchases.first_purchase_date,
DATEDIFF(month, first_purchases.first_purchase_date, EOMONTH(orders.order_purchase_timestamp)) AS age_by_month
FROM orders
INNER JOIN
(SELECT customer_id, MIN(order_purchase_timestamp) AS first_purchase_date
FROM orders AS orders_ref
GROUP BY customer_id
) AS first_purchases ON orders.customer_id = first_purchases.customer_id
WHERE orders.order_purchase_timestamp BETWEEN '20161001' AND '20180930'
GROUP BY orders.customer_id, first_purchases.first_purchase_date, EOMONTH(orders.order_purchase_timestamp)
ORDER BY order_purchase_timestamp;
结果-注意它们与您的结果不同,因为您希望最早的日期是1/10/2016。
customer_id order_purchase_timestamp first_purchase_date age_by_month
1 2016-10-04 00:00:00.000 2016-09-04 00:00:00.000 1
编辑:因为别人会这么做的!您可以通过一次读取来完成此操作,这可能会运行得更快一些。它也短了一点,但在我看来更难理解。
下面使用窗口函数来计算客户最早的购买,以及每个月最早的购买(并使用DISTINCT而不是GROUP BY)。这样,它只执行DATEDIFF来计算差值。
WITH monthly_orders AS
(SELECT DISTINCT orders.customer_id,
MIN(orders.order_purchase_timestamp) OVER (PARTITION BY orders.customer_id, EOMONTH(orders.order_purchase_timestamp)) AS order_purchase_timestamp,
MIN(orders.order_purchase_timestamp) OVER (PARTITION BY orders.customer_id) AS first_purchase_date
FROM orders)
SELECT *, DATEDIFF(month, first_purchase_date, order_purchase_timestamp) AS age_by_month
FROM monthly_orders
WHERE order_purchase_timestamp BETWEEN '20161001' AND '20180930';
但是请注意,这在结果中有一个不同之处。如果您在一个月内有2个订单,并且您的最低日期筛选器在到之间(例如,订单在15/10和20/10,而您的最低日期是16/10),那么行将不包括,因为该月最早的购买超出了筛选器范围。
还要注意这两个字段以及您使用的日期或日期时间字段的类型-如果您有日期时间而不仅仅是日期,BETWEEN '20161001' AND '20180930'
与>= '20161001' AND < '20181001'
是不一样的
这是一个简短的查询,可以实现所有你想要的(使用的方法的描述是内联的):
declare @test table (
customer_id int,
order_purchase_timestamp date
)
-- some test data
insert into @test values
(1, '2016-09-04'),
(2, '2016-09-05'),
(3, '2016-09-05'),
(3, '2016-09-15'),
(1, '2016-10-04');
select
customer_id,
-- takes care of correct display of first_purchase
format(first_purchase, 'yyyy-MM') first_purchase,
-- used to get the difference in months
datediff(m, first_purchase, order_purchase_timestamp) age_by_month,
order_purchase_timestamp
from (
select
*,
-- window function used to find min value for given column within group
-- for each row
min(order_purchase_timestamp) over (partition by customer_id) first_purchase
from @test
) a
相关内容
- 没有找到相关文章
最新更新
- Jenkins zip调试和发布apk,并希望做archiveArtifacts
- 如何在Oracle XE 21c上下载HR模式?
- r语言 - 是否有可能强制一个特定的变量进入bestglm?
- 从html [web app using flask]中的python文件获取信息
- 磁盘[admin]未配置,请在' config/ filessystems .php '中添加磁盘配置
- 如何从子组件中设置父组件中的变量
- 我如何排序我的捆绑器依赖之间是一个开发依赖或不是?
- Weka RF 不会给出任何混淆矩阵或预期结果
- 我想简化这个javascript代码.有许多子元素
- 如何将列表转换为元组,我尝试了基于谷歌搜索,它从未工作过
- 键和值的哈希集
- 目标链接并不总是出现在iframe中
- 0x800700b7向IIS部署网站错误
- 条形码扫描器何时创建com端口,何时不创建?
- 在SQL中创建一个没有join的视图
- 在React中使用jQuery仅用于更改样式(颜色,边框等)是可以的吗?
- UseState没有更新组件属性
- c语言 - 我有一个将字符串作为参数的函数.v手动输入字符串有效,但使用 scanf 不起作用
- 无法解析google工作表中的范围
- 如何在顺风中使用柔韧
- 无法将数据插入数据库
- r语言 - 闪亮的应用程序输出显示在控制台,而不是在主面板
- ModuleNotFoundError for 'sklearn' as subdependency of numpy
- 语句中未声明的标识符导致的负索引'for'
- MariaDB vs MySQL:列定义中的默认表达式不工作
- 在SQL表中有一个默认时间
- vb.net stream_writer encoding
- 我们可以在powershell中调用Bat命令而不调用/调用Bat文件吗?
- 如何修复类型错误:'int'对象不可迭代
- Discord Bot JS:编辑来自先前斜杠命令交互的回复
热门标签:
javascript python java c# php android html jquery c++ css ios sql mysql arrays asp.net json python-3.x ruby-on-rails .net sql-server django objective-c excel regex ruby linux ajax iphone xml vba spring asp.net-mvc database wordpress string postgresql wpf windows xcode bash git oracle list vb.net multithreading eclipse algorithm macos powershell visual-studio image forms numpy scala function api selenium