如何利用子查询结果,用单条SQL筛选符合订购条件的客户?
解决方案:用单条SQL筛选符合条件的客户
当然可行!你的思路完全没问题——先锁定Smith客户2013年的所有订购产品,再找出2014年覆盖了这些产品的客户。下面我结合常见的电商表结构(假设你有customers、orders、order_items三张表),给你两种实用的实现方式:
方法1:通过计数匹配判断全覆盖
这种方法逻辑直观:先统计Smith 2013年订购的去重产品总数,再统计2014年每个客户订购的这些产品的去重数量,两者相等就说明该客户覆盖了所有目标产品。
SELECT c.customer_id, c.name FROM customers c JOIN orders o ON c.customer_id = o.customer_id JOIN order_items oi ON o.order_id = oi.order_id WHERE YEAR(o.order_date) = 2014 -- 只关注Smith 2013年订购过的产品 AND oi.product_id IN ( SELECT DISTINCT oi_smith.product_id FROM customers c_smith JOIN orders o_smith ON c_smith.customer_id = o_smith.customer_id JOIN order_items oi_smith ON o_smith.order_id = oi_smith.order_id WHERE c_smith.name = 'Smith' AND YEAR(o_smith.order_date) = 2013 ) GROUP BY c.customer_id, c.name -- 客户订购的目标产品数 = Smith的目标产品总数 HAVING COUNT(DISTINCT oi.product_id) = ( SELECT COUNT(DISTINCT oi_smith.product_id) FROM customers c_smith JOIN orders o_smith ON c_smith.customer_id = o_smith.customer_id JOIN order_items oi_smith ON o_smith.order_id = oi_smith.order_id WHERE c_smith.name = 'Smith' AND YEAR(o_smith.order_date) = 2013 );
注意点:
- 必须用
COUNT(DISTINCT),避免客户多次订购同一产品导致计数虚高; - 如果你的
orders表直接包含product_id(不需要order_items),去掉order_items的关联即可。
方法2:用NOT EXISTS反推无遗漏
这种方法逻辑更严谨:找2014年的客户,不存在任何一个Smith 2013年的产品是该客户没订购的。适合产品数量较多、需要高效查询的场景。
SELECT DISTINCT c.customer_id, c.name FROM customers c JOIN orders o ON c.customer_id = o.customer_id WHERE YEAR(o.order_date) = 2014 AND NOT EXISTS ( -- 子查询:检查是否存在Smith的产品,该客户2014年没订购 SELECT 1 FROM ( -- Smith 2013年的所有去重产品 SELECT DISTINCT oi_smith.product_id FROM customers c_smith JOIN orders o_smith ON c_smith.customer_id = o_smith.customer_id JOIN order_items oi_smith ON o_smith.order_id = oi_smith.order_id WHERE c_smith.name = 'Smith' AND YEAR(o_smith.order_date) = 2013 ) smith_products WHERE NOT EXISTS ( -- 检查该客户2014年是否订购了当前Smith的产品 SELECT 1 FROM orders o_cust JOIN order_items oi_cust ON o_cust.order_id = oi_cust.order_id WHERE o_cust.customer_id = c.customer_id AND YEAR(o_cust.order_date) = 2014 AND oi_cust.product_id = smith_products.product_id ) );
优势:
- 不需要额外的计数统计,逻辑上直接对应“至少订购所有产品”的需求;
- 数据库对
NOT EXISTS的优化通常较好,大表查询时性能可能更优。
内容的提问来源于stack exchange,提问作者Bohao LI
相关产品推荐
相关产品推荐

