2010-06-21 8 views
5

sagen, es gibt solche Tabelle:Mysql: Wie Gruppen mit bestimmten Werten auswählen?

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 auswählen, die sowohl 1 als auch 3 haben tag_id s, so in diesem Beispiel ist es nur 1. Ich dachte an etwas wie SELECT post_id FROM tags GROUP BY post_id HAVING ... Nach dem ich möchte tag_id s, die in dieser Gruppe vorhanden sind, auflisten. Wie mache ich das?

Antwort

5

Wenn post_id und tag_id sowohl eine eindeutige Einschränkung hat, sollte das auch funktionieren:

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

Wenn es keine eindeutigen Einschränkungen versuchen:

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

Danke, ich entschied mich mit 'SELECT post_id FROM tags WHERE tag_id IN (1,3) GROUP BY post_id HABEN COUNT (1) = 2;', was skaliert gut und ist der Lösung am nächsten – htf

1

Ich habe einige Annahmen über Ihre anderen Tabellen gemacht. (Dh, die Sie haben einen Tisch für Beiträge, die ich posts und eines mit tag_id als PK genannt haben, die ich tag_table genannt haben nameclash mit dem Pfosten/tags Tabelle zu vermeiden, die ich sehe, kann man schon tags nennen)

Sie Möchte Beiträge, bei denen kein Tag in der Liste {1,3} existiert, für die kein passender Datensatz mit der entsprechenden Post-ID/Tag-ID existiert, so können Sie ein doppeltes NOT EXISTS-Konstrukt wie unten verwenden.

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 anderer alternativer Ansatz ist die Verwendung von Gruppieren nach und Zählen. A review of approaches to this problem is here.

+0

+1 für den tollsten Link) – htf

2

Sie ein Self-Join versuchen könnte (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 
+0

+1, aber ich werde eine Auswahl zu Ihrer Anfrage hinzufügen. – Fred

+1

Skaliert jedoch nicht wirklich für eine beliebige Anzahl von Tags. –

0

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

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 
+0

Denken Sie nicht, dass die zweite Klausel Ihres OP nützlich ist. – Fred

+0

@Fred hmm .. yeah, du hast Recht - werde updaten – Amarghosh

1
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 

Verwenden Sie GROUP_CONCAT() für die s econd Teil Ihrer Frage

SELECT post_id, 
     GROUP_CONCAT(tag_id ORDER BY tag_id ASC SEPARATOR ',') 
    FROM tags 
Verwandte Themen