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_ids auszuwählen, die beide 1 und 3 tag_ids 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_ids möchten, die in dieser Gruppe vorhanden sind. Wie kann ich das tun?

War es hilfreich?

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
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top