首次下订单时获取日期和唯一客户数
Posted
技术标签:
【中文标题】首次下订单时获取日期和唯一客户数【英文标题】:Getting date, and count of unique customers when first order was placed 【发布时间】:2019-10-27 14:20:27 【问题描述】:我有一个名为 orders
的表,如下所示:
+--------------+---------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+--------------+---------+------+-----+---------+-------+
| id | int(11) | YES | | NULL | |
| memberid | int(11) | YES | | NULL | |
| deliverydate | date | YES | | NULL | |
+--------------+---------+------+-----+---------+-------+
其中包含以下数据:
+------+----------+--------------+
| id | memberid | deliverydate |
+------+----------+--------------+
| 1 | 991 | 2019-10-25 |
| 2 | 991 | 2019-10-26 |
| 3 | 992 | 2019-10-25 |
| 4 | 992 | 2019-10-25 |
| 5 | 993 | 2019-10-24 |
| 7 | 994 | 2019-10-21 |
| 6 | 994 | 2019-10-26 |
| 8 | 995 | 2019-10-26 |
+------+----------+--------------+
我想要一个返回每个唯一日期的结果集,以及一个单独的列,显示当天有多少客户下了他们的第一个订单。
我在以正确方式查询时遇到问题,尤其是当数据包含同一客户同一天的多个订单时。
我的方法是
-
获取在我要查看的时间段内下订单的所有唯一会员 ID
通过比较该时间段前下单的memberid,过滤掉该时间段内首次下单的会员
按交货日期分组,并计算所有唯一的 memberid(但这显然每天单独计算唯一的 memberid!)
下面是对应的SQL:
SELECT deliverydate,COUNT(DISTINCT memberid) FROM orders
WHERE
MemberId IN (SELECT DISTINCT memberid FROM orders WHERE deliverydate BETWEEN '2019-10-25' AND '2019-10-26')
AND NOT
MemberId In (SELECT DISTINCT memberid FROM orders WHERE deliverydate < '2019-10-25')
GROUP BY deliverydate
ORDER BY deliverydate ASC;
但这会导致上述数据如下:
+--------------+--------------------------+
| deliverydate | COUNT(DISTINCT memberid) |
+--------------+--------------------------+
| 2019-10-25 | 2 |
| 2019-10-26 | 2 |
+--------------+--------------------------+
2019-10-26 的计数应该是 1。
感谢任何帮助:)
【问题讨论】:
【参考方案1】:你可以聚合两次:
select first_deliverydate, count(*) cnt
from (
select min(deliverydate) first_deliverydate
from orders
group by memberid
) t
group by first_deliverydate
order by first_deliverydate
子查询为您提供每个成员的第一个订单数据,然后外部查询按第一个订单日期聚合和计数。
此demo on DB Fiddle 与您的示例数据返回:
first_deliverydate | cnt :----------------- | --: 2019-10-21 | 1 2019-10-24 | 1 2019-10-25 | 2 2019-10-26 | 1在 mysql 8.0 中,这也可以通过窗口函数来实现:
select deliverydate first_deliverydate, count(*) cnt
from (
select deliverydate, row_number() over(partition by memberid order by deliverydate) rn
from orders
) t
where rn = 1
group by deliverydate
order by deliverydate
Demo on DB Fiddle
【讨论】:
【参考方案2】:您必须首先弄清楚第一个交货日期是什么时候:
SELECT firstdeliverydate,COUNT(DISTINCT memberid) FROM (
select memberid, min(deliverydate) as firstdeliverydate
from orders
WHERE
MemberId IN (SELECT DISTINCT memberid FROM orders WHERE deliverydate BETWEEN '2019-10-25' AND '2019-10-26')
AND NOT
MemberId In (SELECT DISTINCT memberid FROM orders WHERE deliverydate < '2019-10-25')
group by memberid)
t1
group by firstdeliverydate
【讨论】:
【参考方案3】:使用NOT EXISTS
获取每个客户的第一个订单,然后使用GROUP BY deliverydate
计算下订单的不同客户:
select o.deliverydate, count(distinct o.memberid) counter
from orders o
where not exists (
select 1 from orders
where memberid = o.memberid and deliverydate < o.deliverydate
)
group by o.deliverydate
请参阅demo。 结果:
| deliverydate | counter |
| ------------------- | ------- |
| 2019-10-21 00:00:00 | 1 |
| 2019-10-24 00:00:00 | 1 |
| 2019-10-25 00:00:00 | 2 |
| 2019-10-26 00:00:00 | 1 |
但是,如果您想要表格中所有日期的结果,包括那些没有新客户订单的日期(所以计数器将是 0
):
select d.deliverydate, count(distinct o.memberid) counter
from (
select distinct deliverydate
from orders
) d left join orders o
on o.deliverydate = d.deliverydate and not exists (
select 1 from orders
where memberid = o.memberid and deliverydate < o.deliverydate
)
group by d.deliverydate
【讨论】:
以上是关于首次下订单时获取日期和唯一客户数的主要内容,如果未能解决你的问题,请参考以下文章
LeetCode:Database 64.即时食物配送 II