Sql查询以获取与标志关联的产品

时间:2011-07-12 16:54:25

标签: mysql sql group-by

我有一个如下所示的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;

...不起作用,并给出一个空集。那么正确的查询是什么?

2 个答案:

答案 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