MySQL使用子查询查询同时预约多位指定艺人的客户ID的方法
问题排查与解决方案
原有代码问题分析
- 语法层面:子查询缺少右括号,
ALL关键字用法错误,ALL的作用是要求匹配子查询返回的所有CustomerID,完全不符合需求场景;同时字符串字面量建议使用单引号,部分SQL方言不支持双引号标识字符串。 - 逻辑层面:用
OR筛选出的是预约过任意一位艺人的客户,无法满足「同时预约三位」的要求。 - 关于子查询使用JOIN的疑问:这个用法是合理的,要关联两张表拿到艺人名对应的预约记录,JOIN是正确的操作。
推荐实现方案
方案1:分组聚合筛选(性能更优,写法简洁)
思路:先关联两张表筛选出所有预约过X/Y/Z任意一位的客户记录,再按CustomerID分组,统计每个客户匹配到的不同艺人数量,刚好等于3的就是同时预约了三位的客户。
SELECT e.CustomerID FROM Database.Engagements e JOIN Database.Entertainers ent ON e.EntertainerID = ent.EntertainerID WHERE ent.EntertainerName IN ('X', 'Y', 'Z') GROUP BY e.CustomerID HAVING COUNT(DISTINCT ent.EntertainerName) = 3;
说明:这里加DISTINCT是为了避免同一个客户多次预约同一个艺人导致计数错误,如果业务上同一客户不会重复预约同一个艺人,可以去掉DISTINCT
方案2:多EXISTS子查询(逻辑更直观,适合条件扩展)
思路:分别判断客户是否存在预约X、预约Y、预约Z的记录,三个条件同时满足即可。
SELECT DISTINCT e.CustomerID FROM Database.Engagements e WHERE EXISTS ( SELECT 1 FROM Database.Engagements e1 JOIN Database.Entertainers ent1 ON e1.EntertainerID = ent1.EntertainerID WHERE e1.CustomerID = e.CustomerID AND ent1.EntertainerName = 'X' ) AND EXISTS ( SELECT 1 FROM Database.Engagements e2 JOIN Database.Entertainers ent2 ON e2.EntertainerID = ent2.EntertainerID WHERE e2.CustomerID = e.CustomerID AND ent2.EntertainerName = 'Y' ) AND EXISTS ( SELECT 1 FROM Database.Engagements e3 JOIN Database.Entertainers ent3 ON e3.EntertainerID = ent3.EntertainerID WHERE e3.CustomerID = e.CustomerID AND ent3.EntertainerName = 'Z' );
内容的提问来源于stack exchange,提问作者Tony Correia
相关产品推荐
相关产品推荐

