【问题标题】:mysql negation from multiple entires来自多个条目的mysql否定
【发布时间】:2015-02-22 05:02:40
【问题描述】:
我有一个 customer_products 表,其中包含客户与其正在使用的产品的映射
customer_id product_id
c1 p1
c1 p2
c1 p3
c2 p1
c2 p2
c3 p1
我想获得所有使用 p2 但不使用 p3 的客户。是否可以在不使用嵌套查询的情况下实现这一点
我能够解决嵌套查询连接的问题。但由于嵌套连接太慢,我无法获得所需的性能。
【问题讨论】:
标签:
mysql
join
query-performance
nested-queries
【解决方案1】:
是的,可以使用反连接模式。这是一个左连接,返回所有使用p2 的客户,以及匹配的行(相同的customer_id)但使用p3,然后过滤掉所有匹配的行,在WHERE 子句中使用谓词。
例如:
SELECT cp2.customer_id
FROM customer_products cp2
LEFT
JOIN customer_products cp3
ON cp3.customer_id = cp2.customer_id
AND cp3.product_id = 'p3'
WHERE cp2.product_id = 'p2'
AND cp3.product_id IS NULL
在GROUP BY cp2.customer_id 子句中添加DISTINCT 关键字以消除重复(如果不能保证(customer_id,product_id) 是唯一的。)
适当的索引将提高大型集合的性能。
【解决方案2】:
在having子句中使用条件聚合的查询,以选择至少购买过product_id p2并且从未购买过product_id p3的所有客户
select customer_id
from mytable
where product_id in ('p2','p3')
group by customer_id
having count(case when product_id = 'p2' then 1 end) > 0
and count(case when product_id = 'p3' then 1 end) = 0