晚上好,
我整天都在和这个人搏斗。
我正在尝试更新我的客户表格中的一列,该列会显示次数他们是订阅者。此表是从大数据转储创建的,每个客户都有单独的行,并且每个月他们都是订阅者(为每个月分配一个迭代编号)。名字是独一无二的。它看起来像这样,并显示(例如)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理解它。我很欣赏任何想法。
*编辑 - 我尝试了加入和不存在的替代方案,并且都在10分钟后超时。我相信这是由于主表的大小(约100,000行)。你有什么建议吗?再次感谢所有评论。
**编辑#2 - 添加索引并稍微调整一下表后,两种解决方案都很有效。再次感谢您对这一点的支持。
答案 0 :(得分:1)
查询可能如下所示:
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_codes系列中的所有行,然后计数:只有每个块的最后一行没有后继(date_code + 1
)。
我假设连续的date_codes形成一个订阅(根据我对问题的第一个评论)。因此,不需要Start_Date
和End_Date
的其他信息。
LEFT JOIN / IS NULL
应该比MySQL中的NOT EXISTS
快一点(如@nnichols提供的那样)。customer_name
和date_code
上的索引。像这样:
CREATE INDEX tbl_customer_name ON tbl(customer_name);
CREATE INDEX tbl_date_code ON tbl(date_code);
答案 1 :(得分:1)
我无法100%确定仍然如此,但LEFT JOIN / IS NULL通常比MySQL中的NOT EXISTS更快 -
SELECT t1.customer_name, COUNT(*) AS subscriptions
FROM tbl t1
LEFT JOIN tbl t2
ON t1.customer_name = t2.customer_name
AND t1.date_code + 1 = t2.date_code
WHERE t2.customer_name IS NULL
GROUP BY t1.customer_name
UPDATE 在这两个字段中添加复合索引而不是两个单列索引会显着提升性能 -
CREATE UNIQUE INDEX `UQ_customer_date_code` ON tbl (customer_name, date_code);
我使用一个包含160万条记录的测试表(21个date_codes的100k客户)进行了一些测试。添加此索引后,查询时间减少了约80%。使用LEFT JOIN而不是NOT EXISTS只会将查询时间减少大约15%。