Скажите, что существует такая таблица:
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_id
s, которые имеют и 1 и 3 tag_id
s, таким образом, в этом примере это только 1
. Я думал о чем-то как SELECT post_id FROM tags GROUP BY post_id HAVING ...
После наличия я хотел бы перечислить tag_id
s, которые присутствуют в этой группе. Как я делаю это?
Если нет уникальных ограничений, попробуйте:
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;
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
Вы могли бы попробовать 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
Как насчет
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)
);
Я сделал некоторые предположения относительно других ваших таблиц. (т.е. у вас есть таблица для сообщений, которую я назвал 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)
)
Другой альтернативный подход - использовать «Группировать по и подсчету». Обзор подходов к этой проблеме находится здесь .
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