Pregunta

dicen que no es tal tabla:

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

campo son bastante auto-explicativo. Quiero seleccionar post_ids que tienen de 1 y 3 tag_ids, por lo que en este ejemplo es sólo 1. Pensé en algo así como Después de haber SELECT post_id FROM tags GROUP BY post_id HAVING ... me gustaría tag_ids lista que están presentes en este grupo. ¿Cómo lo hago?

¿Fue útil?

Solución

Si no hay restricciones únicas tratan:

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

O utilice esta cláusula HAVING, si tratara de detectar sólo dos valores tag_id:

HAVING MIN(tag_id) <> MAX(tag_id)

Si post_id y tag_id ambos tienen una restricción única, esto 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;

Otros consejos

Se podría probar 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

He hecho algunas suposiciones acerca de 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 tags llamada)

¿Quieres mensajes donde no existe una etiqueta de la lista {1,3} para el que no existe un registro coincidente con el correspondiente post_id / tag_id esta manera puede utilizar un doble NO EXISTE constructo de la siguiente manera.

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 utilizar GROUP BY y Count. A revisión de los enfoques a este problema es aquí .

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

Uso GROUP_CONCAT () para la segunda parte de su pregunta

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

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

DONDE versión de la solución de 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
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top