Mysql: wie Gruppen mit bestimmten Werten wählen?
Frage
Say gibt es eine solche Tabelle:
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)
Feldnamen sind ziemlich selbsterklärend. Ich möchte post_id
s auszuwählen, die beide 1 und 3 tag_id
s haben, so in diesem Beispiel ist es nur 1
. Ich dachte an so etwas wie
SELECT post_id FROM tags GROUP BY post_id HAVING ...
Nachdem ich zur Liste tag_id
s möchten, die in dieser Gruppe vorhanden sind. Wie kann ich das tun?
Lösung
Wenn es keine eindeutigen Einschränkungen versuchen:
SELECT post_id
FROM tags
WHERE tag_id = 1 OR tag_id = 3
GROUP BY post_id
HAVING count(DISTINCT tag_id) = 2;
oder benutzen Sie diese HAVING
Klausel, wenn versucht, nur zwei tag_id
Werte zu erkennen:
HAVING MIN(tag_id) <> MAX(tag_id)
Wenn post_id und tag_id beide haben eine eindeutige Einschränkung, sollte dies auch funktionieren:
SELECT post_id
FROM tags
WHERE tag_id = 1 OR tag_id = 3
GROUP BY post_id
HAVING count(*) = 2;
Andere Tipps
Sie könnten versuchen, ein Self-Join (N tag_id -> N kommen), aber es ist wahrscheinlich nicht schnell
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
Ich habe einige Annahmen über Ihre andere Tabellen gemacht. (Das heißt, dass Sie einen Tisch für Beiträge, dass ich posts
und eine mit tag_id als PK genannt habe, die ich tag_table
genannt habe nameclash mit der Pfosten / tags Tabelle zu vermeiden, dass ich Sie schon Anruf tags
sehen kann)
Sie mögen Beiträge, wo es nicht einen Tag in der Liste existiert {1,3}, für die es keinen passenden Datensatz existiert mit der entsprechenden post_id / tag_id, so dass Sie nicht dem doppelten verwenden können VORHANDEN Konstrukt wie unten.
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)
)
Ein weiterer alternativer Ansatz ist die Gruppierung zu verwenden und Graf. A Überprüfung der Ansätze für dieses Problem ist hier .
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
Mit GROUP_CONCAT () für den zweiten Teil Ihrer Frage
SELECT post_id,
GROUP_CONCAT(tag_id ORDER BY tag_id ASC SEPARATOR ',')
FROM tags
Wie wäre es
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)
);
WHERE-Version von @ Keeper-Lösung
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