2010-06-21 11 views
5

decir que no hay tales tabla:Mysql: cómo seleccionar grupos que tienen ciertos valores?

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) 

nombres de campo son bastante auto-explicativo. Quiero seleccionar post_id s que tengan 1 y 3 tag_id s, por lo que en este ejemplo solo es 1. Pensé en algo como SELECT post_id FROM tags GROUP BY post_id HAVING ... Después de tener me gustaría enumerar tag_id s que están presentes en este grupo. ¿Cómo puedo hacer eso?

Respuesta

5

Si post_id y tag_id tanto tienen una restricción única, que debería funcionar también:

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

Si no hay restricciones únicas tratan:

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

Gracias, decidí ir con 'SELECT post_id FROM tags DONDE tag_id IN (1,3) GROUP BY post_id QUE TIENE COUNT (1) = 2;', que se adapta bien y es lo más cercano a su solución – htf

1

He hecho algunas suposiciones sobre sus otras tablas. (Es decir, que tiene una tabla de mensajes que he llamado posts y uno con tag_id como el PK que he llamado tag_table para evitar una nameclash con la tabla de mensajes/tags que puedo ver que ya llama tags)

Usted desea publicaciones donde no exista una etiqueta en la lista {1,3} para la que no exista un registro coincidente con el correspondiente post_id/tag_id, por lo que puede usar una construcción doble NOT EXISTS como se muestra a continuación.

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

Otro enfoque alternativo es usar Agrupar por y contar. A review of approaches to this problem is here.

+0

+1 para el enlace de awesomest) – htf

2

Usted podría intentar un auto join (N tag_id -> N se unen a) pero probablemente no es rápido

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 pero agregaré un seleccionar distinto a su solicitud. – Fred

+1

Sin embargo, realmente no escala para una cantidad arbitraria de etiquetas. –

0

¿Qué tal

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

DONDE versión de @ solución del Guardián

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

No crea que la segunda cláusula de su OR es útil. – Fred

+0

@Fred hmm .. sí, tienes razón - actualizará – 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 

Usar GROUP_CONCAT() para la s egundo parte de su pregunta

SELECT post_id, 
     GROUP_CONCAT(tag_id ORDER BY tag_id ASC SEPARATOR ',') 
    FROM tags 
Cuestiones relacionadas