Mysql: how to select groups having certain values?

后端 未结 6 675
遥遥无期
遥遥无期 2020-11-27 22:17

Say there is such table:

mysql> SELECT * FROM tags;
+---------+--------+
| post_id | tag_id |
+---------+--------+
|       1 |      2 |
|       1 |      3         


        
相关标签:
6条回答
  • 2020-11-27 22:54

    I've made some assumptions about your other tables. (i.e. that you have a table for posts that I have called posts and one with tag_id as the PK which I have called tag_table to avoid a nameclash with the posts/tags table that I can see you already call tags)

    You want posts where there does not exist a tag in the list {1,3} for which there does not exist a matching record with the corresponding post_id/tag_id so you can use a double NOT EXISTS construct as below.

    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)        
        )
    

    Another alternative approach is to use Group By and Count. A review of approaches to this problem is here.

    0 讨论(0)
  • 2020-11-27 22:54

    How about

    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)
      );
    
    0 讨论(0)
  • 2020-11-27 22:58

    If there aren't any unique constraints try:

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

    Or use this HAVING clause, if trying to detect only two tag_id values:

    HAVING MIN(tag_id) <> MAX(tag_id)
    

    If post_id and tag_id both have an unique constraint, this should work too:

    SELECT post_id 
    FROM tags 
    WHERE tag_id = 1 OR tag_id = 3 
    GROUP BY post_id 
    HAVING count(*) = 2;
    
    0 讨论(0)
  • 2020-11-27 22:59

    WHERE version of @Keeper's solution

    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
    
    0 讨论(0)
  • 2020-11-27 23:07

    You could try a self join (N tag_id -> N join) but probably it's not fast

    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
    
    0 讨论(0)
  • 2020-11-27 23:15
    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
    

    Use GROUP_CONCAT() for the second part of your question

    SELECT post_id,
           GROUP_CONCAT(tag_id ORDER BY tag_id ASC SEPARATOR ',')
      FROM tags
    
    0 讨论(0)
提交回复
热议问题