http://sqlfiddle.com/#!4/bab93d
请参阅SQL小提琴示例...我有客户,标签和映射表。我试图通过标签实现客户搜索,它必须是AND搜索。查询将传递一个标记标识符列表(任意数字),并且只能返回包含所有标记的客户。
在示例中,我使用了一个IN运算符,但它对应于OR搜索并且没有解决我的问题。查询应该是什么样的AND搜索?
select
*
from
customer c
inner join customer_tag ct on ct.customer_id = c.customer_id
where
ct.tag_id in (1, 2);
这将返回两个客户,但只有第一个客户被标记为标记1和2。
答案 0 :(得分:3)
您可以使用相关子查询来获取所有客户的列表:
SELECT *
FROM customer c
WHERE c.customer_ID IN
(
SELECT customer_id
FROM customer_tag ct
WHERE ct.customer_id = c.customer_id
AND ct.tag_id IN (1,2)
GROUP BY customer_id
HAVING COUNT(DISTINCT tag_id) = 2
);
的 LiveDemo
强>
很容易扩展:
WHERE ct_tag IN (1,2,3)
...
HAVING COUNT(DISTINCT tag_id) = 3
答案 1 :(得分:3)
JOIN
版本:
SELECT c.*
FROM customer c
JOIN (SELECT customer_id
FROM customer_tag
WHERE tag_id IN (1,2)
GROUP BY customer_id
HAVING MAX(tag_id) <> MIN(tag_id)) ct ON c.customer_id = ct.customer_id
如果您有两个以上不同的值,请改用COUNT DISTINCT
,如下所示:
SELECT c.*
FROM customer c
JOIN (SELECT customer_id
FROM customer_tag
WHERE tag_id IN (1,2,3)
GROUP BY customer_id
HAVING COUNT(DISTINCT tag_id) = 3) ct ON c.customer_id = ct.customer_id
答案 2 :(得分:1)
您可以执行类似
的操作SELECT *
FROM customer c
WHERE
2 = (SELECT COUNT(DISTINCT ct.tag_id)
FROM customer_tag ct
WHERE ct.customer_id = c.customer_id AND ct.tag_id IN (1, 2));
2 = ...
部分应根据您要搜索的代码数量进行调整。
替代解决方案 - 相关子查询可能性能较差,因此您可以加入像这样的表
SELECT c.*
FROM customer c
INNER JOIN (
SELECT ct.customer_id
FROM customer_tag ct
WHERE ct.tag_id IN (1, 2)
GROUP BY ct.customer_id
HAVING COUNT(DISTINCT ct.tag_id) = 2
) ct ON ct.customer_id = c.customer_id;
答案 3 :(得分:1)
扩展其他答案,我将添加一个版本,您不需要计算标签,也不需要列出两次:
WITH tgs as(
select distinct tag_id
from Tags
where tag_id in (1, 2, 3, 4) --modify only here
)
SELECT c.*
FROM customer c
JOIN (SELECT customer_id
FROM customer_tag
WHERE tag_id in (select tag_id from tgs)
GROUP BY customer_id
HAVING COUNT(DISTINCT tag_id) = (select count(*) from tgs)
) ct ON c.customer_id = ct.customer_id
如果表格正确规范化(并且有pks等),您可以删除distinct
个关键字。