我有一个如下所示的flags_products表(标志和产品之间的多对多关系),
flags_products :
flag_id -- product_id
1 -- 1
2 -- 1
3 -- 1
1 -- 2
2 -- 2
4 -- 2
获取具有与产品(product_id)关联的标志(flag_id的1和2)的行的SQL查询是什么?显然:
SELECT *
FROM flags_products
WHERE flag_id = 1
AND flag_id = 2
GROUP BY product_id;
...不起作用,并给出一个空集。那么正确的查询是什么?
答案 0 :(得分:4)
您应采取的确切方法取决于您的更高要求。这是一个可能的解决方案:
SELECT
product_id
FROM
Some_Table
WHERE
flag_id IN (1, 2)
GROUP BY
product_id
HAVING
COUNT(*) = 2
只要您不能重复,这就有效。如果产品可以使用相同的flag_id标记两次,那么您需要:
SELECT
product_id
FROM
Some_Table
WHERE
flag_id IN (1, 2)
GROUP BY
product_id
HAVING
COUNT(DISTINCT flag_id) = 2
在这两种情况下,您都需要GROUP BY
来匹配您的列列表。 MySQL不需要为了运行查询(一个缺陷的IMO,但我会将该参数另外保存一段时间),但是对于不在GROUP BY
中的列,结果将无法确定。您还可以将上述查询用作子查询,然后您可以将其连接到另一个或多个表。
如果您知道它总是正好是您正在寻找的两个标志,那么您可以使用EXISTS:
SELECT
T1.product_id
FROM
Some_Table T1
WHERE
EXISTS (
SELECT *
FROM
Some_Table T2
WHERE
T2.product_id = T1.product_id AND
T2.flag_id = 1
) AND
EXISTS (
SELECT *
FROM
Some_Table T2
WHERE
T2.product_id = T1.product_id AND
T2.flag_id = 2
)
虽然表现可能不太好。
答案 1 :(得分:0)
您可以使用INTERSECT
运算符。
SELECT product_id
FROM t
WHERE flag_id = 1
INTERSECT
SELECT product_id
FROM t
WHERE flag_id = 2
此查询将返回同时包含product_id
flag_id = 1 or 2