【问题标题】:Mysql: how to select groups having certain values?Mysql:如何选择具有特定值的组?
【发布时间】:2011-03-06 05:36:34
【问题描述】:

说有这样的表:

mysql> SELECT * FROM tags;
+---------+--------+
| post_id | tag_id |
+---------+--------+
|       1 |      2 |
|       1 |      3 |
|       1 |      1 |
|       2 |      1 |
|       2 |      2 |
+---------+--------+
5 rows in set (0.00 sec)

字段名称是不言自明的。我想选择同时具有 1 和 3 个tag_ids 的post_ids,所以在这个例子中它只有1。我想到了类似的东西 SELECT post_id FROM tags GROUP BY post_id HAVING ... 之后我想列出该组中的tag_ids。我该怎么做?

【问题讨论】:

    标签: sql mysql group-by having


    【解决方案1】:

    如果没有任何唯一约束尝试:

    SELECT post_id 
    FROM tags 
    WHERE tag_id = 1 OR tag_id = 3 
    GROUP BY post_id 
    HAVING count(DISTINCT tag_id) = 2;
    

    如果尝试仅检测两个 tag_id 值,则使用此 HAVING 子句:

    HAVING MIN(tag_id) <> MAX(tag_id)
    

    如果 post_id 和 tag_id 都具有唯一约束,这也应该有效:

    SELECT post_id 
    FROM tags 
    WHERE tag_id = 1 OR tag_id = 3 
    GROUP BY post_id 
    HAVING count(*) = 2;
    

    【讨论】:

    • 谢谢,我决定使用SELECT post_id FROM tags WHERE tag_id IN (1,3) GROUP BY post_id HAVING COUNT(1) = 2;,它可以很好地扩展并且最接近您的解决方案
    【解决方案2】:
    SELECT post_id
      FROM ( SELECT post_id,
                    count(tag_id) AS counter
               FROM tags
              WHERE tag_id IN (1,3)
              GROUP BY post_id
           )
     WHERE counter = 2
    

    在问题的第二部分使用 GROUP_CONCAT()

    SELECT post_id,
           GROUP_CONCAT(tag_id ORDER BY tag_id ASC SEPARATOR ',')
      FROM tags
    

    【讨论】:

      【解决方案3】:

      @Keeper 解决方案的 WHERE 版本

      SELECT DISTINCT t1.post_id 
      FROM tags t1, tags t2
      WHERE 
        t1.post_id = t2.post_id  AND 
        t1.tag_id = 1 AND t2.tag_id = 3
      

      【讨论】:

      • 不要认为你的 OR 的第二个子句有用。
      【解决方案4】:

      我对您的其他表格做了一些假设。 (即,您有一张我称之为posts 的帖子的表格和一个以tag_id 作为PK 的表格,我称之为tag_table,以避免与帖子/标签表格发生名称冲突,我可以看到您已经致电tags )

      您希望在列表 {1,3} 中不存在标签的帖子中不存在与相应 post_id/tag_id 匹配的记录,因此您可以使用如下所示的双重 NOT EXISTS 构造。

      SELECT post_id
      FROM posts p
      WHERE NOT EXISTS 
          (SELECT * FROM tag_table tt
          WHERE tag_id IN (1,3)
          AND NOT EXISTS
              (SELECT * FROM tags t
              WHERE t.tag_id = tt.tag_id  and
              p.post_id = t.post_id)        
          )
      

      另一种替代方法是使用 Group By 和 Count。 A review of approaches to this problem is here.

      【讨论】:

        【解决方案5】:

        怎么样

        SELECT * 
        FROM tags 
        WHERE post_id in 
          (SELECT post_id AS pid 
           FROM tags 
           WHERE 1 IN (SELECT tag_id FROM tags WHERE post_id = pid) 
           AND 3 IN (SELECT tag_id FROM tags WHERE post_id = pid)
          );
        

        【讨论】:

        • 这个答案缺少教育解释。
        【解决方案6】:

        您可以尝试自连接(N tag_id -> N join),但可能速度不快

        SELECT t1.post_id 
        FROM tags t1 INNER JOIN tags t2 ON t1.post_id = t2.post_id 
        WHERE t1.tag_id = 1 AND t2.tag_id = 3
        

        【讨论】:

        • 虽然不能真正扩展任意数量的标签。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-05-07
        • 1970-01-01
        • 1970-01-01
        • 2022-01-17
        • 1970-01-01
        相关资源
        最近更新 更多