Mysql: как выбрать группы, имеющие определенные значения?

Скажите, что существует такая таблица:

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)

Имена полей довольно очевидны. Я хочу выбрать post_ids, которые имеют и 1 и 3 tag_ids, таким образом, в этом примере это только 1. Я думал о чем-то как SELECT post_id FROM tags GROUP BY post_id HAVING ... После наличия я хотел бы перечислить tag_ids, которые присутствуют в этой группе. Как я делаю это?

6
задан htf 21 June 2010 в 09:24
поделиться

6 ответов

Если нет уникальных ограничений, попробуйте:

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;
9
ответ дан 8 December 2019 в 18:32
поделиться
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
1
ответ дан 8 December 2019 в 18:32
поделиться

Вы могли бы попробовать self join (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
2
ответ дан 8 December 2019 в 18:32
поделиться

Как насчет

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
ответ дан 8 December 2019 в 18:32
поделиться

Я сделал некоторые предположения относительно других ваших таблиц. (т.е. у вас есть таблица для сообщений, которую я назвал posts , и таблица с tag_id в качестве ПК, которую я назвал tag_table , чтобы избежать столкновения имен с таблицей сообщений / тегов, которую я видно, что вы уже вызываете тегов )

Вам нужны сообщения, в которых нет тега в списке {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)        
    )

Другой альтернативный подход - использовать «Группировать по и подсчету». Обзор подходов к этой проблеме находится здесь .

1
ответ дан 8 December 2019 в 18:32
поделиться

WHERE версия решения @Keeper

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
ответ дан 8 December 2019 в 18:32
поделиться
Другие вопросы по тегам:

Похожие вопросы: