大家晚上好
我整天都在和这个问题搏斗。
我正在尝试更新我的客户表中的一列,该列将显示他们成为订阅者的次数。这个表是从一个大数据转储创建的,每个客户都有单独的行,每个月他们都是订阅者(每个月分配一个迭代数字)。名字是独一无二的。它看起来像这样并表明(例如)Jane Doe 是期间 1000 的订阅者,但不是期间 1002 的订阅者。
Row_ID Customer_Name Date_Code
1 Jane Doe 1000
2 Jane Doe 1001
3 Jane Doe 1004
4 Jane Doe 1005
5 Ted Jones 1000
6 Ted Jones 1001
7 Ted Jones 1002
etc...
在这种情况下,Jane Doe 是 1000-1001 的订阅者,离开我们的订阅,然后从 1004-1005 回来。我有一个包含所有日期逻辑(开始日期、结束日期、日期代码等)的主表。它看起来大致是这样的:
Start_Date End_Date Date_Code
1990-01-01 1990-03-31 1000
1990-04-01 1990-06-30 1001
1990-07-01 1990-09-30 1002
1990-10-01 1990-12-31 1003
etc...
我正试图找到一种方法使输出类似于:
Customer_Name Subscription_Count
Jane Doe 2
Ted Jones 1
有没有人遇到过这样的事情?对我来说(作为一个人)很明显数字是(或不)连续的并且是(或不是)整个样本的表示,但我不确定如何让 MYSQL 理解它。我很感激任何想法。
*编辑 - 我尝试了 Join 和 Where Not Exists 两种替代方法,但都在 10 分钟后超时。我相信这是由于主表的大小(~100,000 行)。你有什么建议吗?再次感谢所有评论。
**编辑 #2 - 添加索引并稍微调整我的表后,两种解决方案都很好用。再次感谢您对解决这个问题的支持。
最佳答案
查询可能看起来像这样:
SELECT customer_name, count(*) AS subscriptions
FROM tbl AS t
WHERE NOT EXISTS (
SELECT *
FROM tbl AS t1
WHERE t1.customer_name = t.customer_name
AND t1.date_code = t.date_code + 1
)
GROUP BY customer_name;
这里的技巧是排除所有行,但每个客户的 date_code 系列中只有一个行,然后计数:每个 block 只有最后一行没有后继行(date_code + 1
)。
我假设连续的 date_codes 形成一个订阅(根据我对问题的第一条评论)。因此,有关 Start_Date
的附加信息和 End_Date
不需要。
性能
LEFT JOIN / IS NULL
实际上应该比 NOT EXISTS
快一点在 MySQL 中(由@nnichols 提供)。
对于性能来说更重要的是索引。为了加快速度,您需要在 customer_name
上建立索引和 date_code
.像这样:
CREATE INDEX tbl_customer_name ON tbl(customer_name);
CREATE INDEX tbl_date_code ON tbl(date_code);
关于MYSQL:连续日期的表更新,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9651730/