Mysql:如何选择具有特定值的组?

发布于 2024-09-06 17:53:05 字数 508 浏览 11 评论 0原文

假设有这样一个表:

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_idpost_id,因此在本例中只有 1。我想到了类似的东西 SELECT post_id FROM Tags GROUP BY post_id HAVING ... 拥有后,我想列出该组中存在的tag_id。我该怎么做?

Say there is such table:

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)

Field names are pretty self-explanatory. I want to select post_ids that have both 1 and 3 tag_ids, so in this example it's only 1. I thought of something like
SELECT post_id FROM tags GROUP BY post_id HAVING ... After having I'd like to list tag_ids that are present in this group. How do I do that?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

同展鸳鸯锦 2024-09-13 17:53:05

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

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

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

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;

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;
心奴独伤 2024-09-13 17:53:05

您可以尝试自连接(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

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
宣告ˉ结束 2024-09-13 17:53:05
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
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
寂寞陪衬 2024-09-13 17:53:05

我对你的其他桌子做了一些假设。 (即,您有一个我称为 posts 的帖子表和一个以 tag_id 作为 PK 的表,我将其称为 tag_table 以避免与 posts/tags 表发生名称冲突我可以看到您已经调用了 tags

您想要列表 {1,3} 中不存在标签的帖子,而列表 {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对此问题的解决方法的回顾在这里

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.

花海 2024-09-13 17:53:05

怎么样

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

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)
  );
很快妥协 2024-09-13 17:53:05

@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

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
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文