Foros del Web » Programación para mayores de 30 ;) » Bases de Datos General » Mysql »

Consulta simple M2M!

Estas en el tema de Consulta simple M2M! en el foro de Mysql en Foros del Web. Hola a todos! Veamos..., tengo la siguiente tablita m2m: archivos_etiquetas archivo_id etiqueta_id Consulta: traer los archivos que tengan las etiquetas 1 y 2. OPCIÓN 1: ...
  #1 (permalink)  
Antiguo 08/03/2008, 09:23
Avatar de Hereje  
Fecha de Ingreso: junio-2002
Ubicación: Córdoba, Argentina
Mensajes: 439
Antigüedad: 21 años, 10 meses
Puntos: 2
Consulta simple M2M!

Hola a todos!

Veamos..., tengo la siguiente tablita m2m:

archivos_etiquetas
  • archivo_id
  • etiqueta_id

Consulta: traer los archivos que tengan las etiquetas 1 y 2.

OPCIÓN 1: Intersección

Código:
(SELECT archivo_id FROM archivos_etiquetas WHERE etiqueta_id = 1)
INTERSECTION
(SELECT archivo_id FROM archivos_etiquetas WHERE etiqueta_id = 2)
Pero por lo que veo MySQL no lo implementa! Podrá ser?

De todas formas, con este método, habría que hacer tantas intersecciones como cantidad de etiqutas a incluir en la consulta. Como que no me gusta mucho.

OPCIÓN 2: Subconsultas

Código:
SELECT archivo_id FROM archivos_etiquetas WHERE
archivo_id IN (SELECT archivo_id FROM archivos_etiquetas WHERE etiqueta_id = 1) AND
archivo_id IN (SELECT archivo_id FROM archivos_etiquetas WHERE etiqueta_id = 2)
Este me gusta más, funciona, pero no se..., muchas subconsultas también.

¿Alguien podria plantear alguna alternativa?

Saludos y gracias!
__________________
Sergio
  #2 (permalink)  
Antiguo 08/03/2008, 09:32
Avatar de gnzsoloyo
Moderador criollo
 
Fecha de Ingreso: noviembre-2007
Ubicación: Actualmente en Buenos Aires (el enemigo ancestral)
Mensajes: 23.324
Antigüedad: 16 años, 4 meses
Puntos: 2658
Re: Consulta simple M2M!

¿No te resultaría más sencillo hacer algo como:
Código:
SELECT archivo_id FROM archivos_etiquetas WHERE etiqueta_id IN(1,2);
  #3 (permalink)  
Antiguo 08/03/2008, 12:05
Avatar de Hereje  
Fecha de Ingreso: junio-2002
Ubicación: Córdoba, Argentina
Mensajes: 439
Antigüedad: 21 años, 10 meses
Puntos: 2
Re: Consulta simple M2M!

Es un chiste?

Eso es un OR y yo quiero un AND.
__________________
Sergio
  #4 (permalink)  
Antiguo 08/03/2008, 18:28
Avatar de gnzsoloyo
Moderador criollo
 
Fecha de Ingreso: noviembre-2007
Ubicación: Actualmente en Buenos Aires (el enemigo ancestral)
Mensajes: 23.324
Antigüedad: 16 años, 4 meses
Puntos: 2658
Re: Consulta simple M2M!

Cita:
Iniciado por Hereje;
Es un chiste?

Eso es un OR y yo quiero un AND.
No es un chiste:
1. El ejemplo de tablas que estás indicando implica que tienes una tabla que cuenta con una clave primaria y un sólo atributo más. Además, se presupone que uno sólo de ellos debe ser PK, o los dos juntos.
2. Eso implica que solamente quieres los ID de los que tengan uno u otro número en el segundo atributo, ya que por definición, un atributo no puede ser multivaluado. Siendo que la PK no puede repetirse, los registros sólo pueden contener UNO U OTRO valor y NO AMBOS A LA VEZ.
5. En ese caso, siendo que lo que quieres es el listado de todos los registros en donde ID_Archivo donde el valor de id_etiqueta sea 1 o 2 , lo que corresponde es usan un IN().
5. Si es posible que exista más de un valor en el mismo atributo, o no estás describiendo total y correctamente las tablas, o bien el diseño de datos no está normalizado.
  #5 (permalink)  
Antiguo 09/03/2008, 14:38
Avatar de matanga  
Fecha de Ingreso: octubre-2007
Ubicación: España
Mensajes: 1.091
Antigüedad: 16 años, 5 meses
Puntos: 85
Re: Consulta simple M2M!

Hola,

Esta consulta puede ayudarte, si necesitas que la condicion sea 1,2 y 3, lo cambias en el IN y el HAVING count(*) > 2, y asi sucesivamente. Se entiende eid por etiqueta_id y aid por archivo_id.

Código:
SQL> select * from t1 a
  2  where exists
  3  (select count(*) from t1 b
  4  where eid in (1,2) and a.aid = b.aid
  5  having count(*) > 1
  6* )
Pd1, no lo tengo probado en MySQL, solo en Oracle.

Cita:
Es un chiste?

Eso es un OR y yo quiero un AND.
Pd2, Intenta cuidar los modales, que el foro es cosa de voluntarios, y deberias agradecer que alguien se interese en responder tu pregunta.

Saludos
  #6 (permalink)  
Antiguo 10/03/2008, 05:01
Avatar de gnzsoloyo
Moderador criollo
 
Fecha de Ingreso: noviembre-2007
Ubicación: Actualmente en Buenos Aires (el enemigo ancestral)
Mensajes: 23.324
Antigüedad: 16 años, 4 meses
Puntos: 2658
Re: Consulta simple M2M!

Después de leer mejor tu consulta, te propongo esto:
Código:
SELECT T2.archivo_Id 
FROM archivos_etiquetas 
INNER JOIN 
   (SELECT archivo_id 
    FROM archivos_etiquetas WHERE etiqueta_id IN(1)
   ) AS t1 USING(archivo_id) 
WHERE T2.etiqueta_id IN(2) ;
¿Por qué usar IN y no HAVING o a = b?
Porque la comparación de HAVING y una comparación a = b, se hace sobre la tabla resultado de la selección, incluyendo resultados parciales, mientras que IN omite los registros que no cumplen la condición, mientras los lee de la tabla.
  #7 (permalink)  
Antiguo 10/03/2008, 06:49
Avatar de Hereje  
Fecha de Ingreso: junio-2002
Ubicación: Córdoba, Argentina
Mensajes: 439
Antigüedad: 21 años, 10 meses
Puntos: 2
Re: Consulta simple M2M!

Perdón por mis modales, muchas gracias por intentar ayudarme gnzsoloyo!

Matanga, gracias por tu ayuda. Pero en MySQL los resultados no son los deseados :(

Gracias nuevamente! Actualmente estoy implementando la OPCIÓN 2, y va a los tiros, ya vamos a ver cuando tenga muchos registros.

Saludos!
__________________
Sergio
  #8 (permalink)  
Antiguo 10/03/2008, 06:49
Avatar de matanga  
Fecha de Ingreso: octubre-2007
Ubicación: España
Mensajes: 1.091
Antigüedad: 16 años, 5 meses
Puntos: 85
Re: Consulta simple M2M!

Hola,

No estoy seguro de estar de acuerdo, pero en fin, las dos consultas cumplen con la condicion.

Código:
mysql> select * from t1;
+------+------+
| aid  | eid  |
+------+------+
|    1 |    1 |
|    1 |    2 |
|    2 |    1 |
|    2 |    2 |
|    3 |    1 |
|    4 |    1 |
|    5 |    1 |
|    5 |    2 |
+------+------+
8 rows in set (0.00 sec)
Código:
mysql> explain
    -> select distinct a.aid from t1 a
    -> where exists
    -> (select count(*) from t1 b
    -> where eid in (1,2) and a.aid = b.aid
    -> having count(*) > 1
    -> );
+----+--------------------+-------+------+---------------+------+---------+------+------+------------------------------+
| id | select_type        | table | type | possible_keys | key  | key_len | ref  | rows | Extra                        |
+----+--------------------+-------+------+---------------+------+---------+------+------+------------------------------+
|  1 | PRIMARY            | a     | ALL  | NULL          | NULL | NULL    | NULL |    8 | Using where; Using temporary |
|  2 | DEPENDENT SUBQUERY | b     | ALL  | NULL          | NULL | NULL    | NULL |    8 | Using where                  |
+----+--------------------+-------+------+---------------+------+---------+------+------+------------------------------+
2 rows in set (0.00 sec)
Código:
mysql> explain
    -> SELECT T2.aId
    -> FROM t1 t2
    -> INNER JOIN
    ->    (SELECT aid
    ->     FROM t1 WHERE eid IN(1)
    ->    ) AS t2 USING(aid)
    -> WHERE T2.eid IN(2) ;
+----+-------------+------------+------+---------------+------+---------+------+------+-------------+
| id | select_type | table      | type | possible_keys | key  | key_len | ref  | rows | Extra       |
+----+-------------+------------+------+---------------+------+---------+------+------+-------------+
|  1 | PRIMARY     | <derived2> | ALL  | NULL          | NULL | NULL    | NULL |    5 |             |
|  1 | PRIMARY     | t2         | ALL  | NULL          | NULL | NULL    | NULL |    8 | Using where |
|  2 | DERIVED     | t1         | ALL  | NULL          | NULL | NULL    | NULL |    8 | Using where |
+----+-------------+------------+------+---------------+------+---------+------+------+-------------+
3 rows in set (0.00 sec)
Saludos
  #9 (permalink)  
Antiguo 10/03/2008, 06:51
Avatar de matanga  
Fecha de Ingreso: octubre-2007
Ubicación: España
Mensajes: 1.091
Antigüedad: 16 años, 5 meses
Puntos: 85
Re: Consulta simple M2M!

Hola,

Cita:
Matanga, gracias por tu ayuda. Pero en MySQL los resultados no son los deseados :(
Si tienes razon, recien lo veo, me falto un distinct.

Saludos
  #10 (permalink)  
Antiguo 10/03/2008, 07:24
Avatar de gnzsoloyo
Moderador criollo
 
Fecha de Ingreso: noviembre-2007
Ubicación: Actualmente en Buenos Aires (el enemigo ancestral)
Mensajes: 23.324
Antigüedad: 16 años, 4 meses
Puntos: 2658
Re: Consulta simple M2M!

El efecto de IN() no se percibe dentro de tablas reducidas.
Vamos a inventar un poco. Prueba esto:
Código:
SELECT archivo_id, count(*) etiquetas  
FROM archivos_etiquetas 
WHERE etiqueta_id IN(1,2) 
GROUP BY  archivo_id 
HAVING etiquetas=2;
Te devolverá dos campos, pero debería devolverte en el primero la lista que necesitas.
  #11 (permalink)  
Antiguo 10/03/2008, 07:39
Avatar de matanga  
Fecha de Ingreso: octubre-2007
Ubicación: España
Mensajes: 1.091
Antigüedad: 16 años, 5 meses
Puntos: 85
Re: Consulta simple M2M!

Hola gnzsoloyo,

Esa es!, la mejor opcion, 1 solo full scan, 0 joins y una funcion de agregado, buen post.

Saludos
  #12 (permalink)  
Antiguo 10/03/2008, 13:04
Avatar de Hereje  
Fecha de Ingreso: junio-2002
Ubicación: Córdoba, Argentina
Mensajes: 439
Antigüedad: 21 años, 10 meses
Puntos: 2
Re: Consulta simple M2M!

Ohhhhhh !!! Qué bien !!!

Muchas gracias !! Un gran abrazo a ambos por su tiempo !!
__________________
Sergio
Atención: Estás leyendo un tema que no tiene actividad desde hace más de 6 MESES, te recomendamos abrir un Nuevo tema en lugar de responder al actual.
Respuesta




La zona horaria es GMT -6. Ahora son las 14:37.