COUNT 数字在时间段之前不存在时不同
Posted
技术标签:
【中文标题】COUNT 数字在时间段之前不存在时不同【英文标题】:COUNT number distinct when they a row hasn't existed before the time period 【发布时间】:2020-01-31 01:28:11 【问题描述】:我有一种有趣的情况,我会尽力解释。
我有一张名为appointments
的表,其中包含销售人员可以与潜在客户进行的许多约会。与销售人员的约会是多对一的关系,对于潜在客户也是如此。
我需要计算一个销售人员与潜在客户安排了多少次约会而该销售人员以前从未与该潜在客户安排过约会。
这是我在代码中的进展情况(我试图查看销售人员昨天设置了多少约会,因此日期擦洗):
SELECT COUNT(DISTINCT lead)
FROM appointments
WHERE status = 3
and DATE(appointment_created_at) = CURDATE() - interval 1 day
AND creator = 'xxx';
(creator
列代表个人销售人员,lead
列代表个人潜在客户)
此 SQL 查询的问题在于,如果销售人员重置与他们已经设置约会的潜在客户的约会,它仍将其视为“已设置约会”。
如何在不计算之前已设置的潜在客户的情况下计算约会表中的行数?
【问题讨论】:
【参考方案1】:您可以使用NOT EXISTS()
来检查之前是否已经存在约会。
SELECT COUNT(DISTINCT a1.lead)
FROM appointments a1
WHERE a1.status = 3
and a1.appointment_created_at >= CURRENT_DATE() - INTERVAL 1 DAY
AND a1.appointment_created_at < CURRENT_DATE()
AND a1.creator = 'xxx'
AND NOT EXISTS (SELECT 1
FROM appointments a2
WHERE a2.creator = 'xxx'
AND a2.lead = a1.lead
AND a2.appointment_created_at < a1.appointment_created_at)
为了获得良好的性能,对于 NOT EXISTS()
部分中的 Correlated 子查询,您可以使用以下复合索引:(creator, lead, appointment_created_at)
并且,对于主选择查询,您可以添加以下复合索引:(creator, status, appointment_created_at)
【讨论】:
【参考方案2】:如果您想要“首次”约会的数量,可以使用row_number()
或相关子查询:
SELECT COUNT(*)
FROM appointments a
WHERE a.status = 3 AND
a.appointment_created_at >= CURDATE() - interval 1 day AND
a.appointment_created_at < CURDATE() AND
a.creator = 'xxx' AND
a.appointment_created_at = (SELECT MIN(a2.appointment_created_at)
FROM appointments a2
WHERE a2.creator = a.creator AND
a2.lead = a.lead
);
请注意,我更改了日期比较,因此可以将索引用于WHERE
子句。如果您关心性能,则需要以下索引:
appointments(creator, status, appointment_created_at, lead)
appointments(creator, lead, appointment_created_at)
。
【讨论】:
【参考方案3】:如果销售人员可以重新安排约会,那么您至少需要一个额外的字段来存储原始约会日期。还有其他更复杂的解决方案,但这可能是最简单的方法。
【讨论】:
以上是关于COUNT 数字在时间段之前不存在时不同的主要内容,如果未能解决你的问题,请参考以下文章
为啥 SQL 计数(*)与 SQL 计数(数字)存在行为差异
SQL Count Distinct Value Oldest DateTime