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

[SOLUCIONADO] Inner Join no devuelve nada

Estas en el tema de Inner Join no devuelve nada en el foro de Bases de Datos General en Foros del Web. Buenas a to2, Tengo un pequeño problema, al intentar obtener cualquier resultado incluyendo en el where más de una condicion, me devuelve un conjunto vacio. ...
  #1 (permalink)  
Antiguo 30/05/2013, 03:35
 
Fecha de Ingreso: abril-2010
Mensajes: 298
Antigüedad: 14 años
Puntos: 1
Inner Join no devuelve nada

Buenas a to2,

Tengo un pequeño problema, al intentar obtener cualquier resultado incluyendo en el where más de una condicion, me devuelve un conjunto vacio.
Quiero obtener los restaurantes que tengan los servicios con id=1 e id=2

He probado con left outer y right outer porque es un tema que no domino , y sigo sin obtener nada.

la tabla principal es restaurantes y esta tiene una relacion M a N con servicios y tiposCocina(con esta tabla tengo el mismo problema...).



Código MySQL:
Ver original
  1. `restaurantes` `t`  LEFT OUTER JOIN `serviciosrestaurantes`
  2. `servicios_servicios` ON (`t`.`id`=`servicios_servicios`.`restaurantes_id`)
  3. LEFT OUTER JOIN `servicios` `servicios` ON
  4. (`servicios`.`id`=`servicios_servicios`.`servicios_id`)  WHERE
  5. (servicios.id=1 and servicios.id=2) LIMIT 10

PD:La sql me la genera mi framework, como ya he comentado antes no me manejo muy bien con esto...


Última edición por ferminako; 30/05/2013 a las 05:07
  #2 (permalink)  
Antiguo 30/05/2013, 05:36
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
Respuesta: Inner Join no devuelve nada

Código MySQL:
Ver original
  1. (servicios.id=1 AND servicios.id=2)
Esta es una condición de cumplimiento imposible.
La evaluación del WHERE se cumple sobre cada uno de los registros, considerados independientemente, es decir que para que esas dos condiciones se cumplan ese único campo debe tener el valor 1 y 2 al mismo tiempo, cosa total y absolutamente imposible.
La condición a colocar es IN(), o bien OR.
Además de esto, en realidad no estás haciendo un INNER JOIN, sino un LEFT JOIN, que tiene resultados completamente distintos.
Ahora bien, como nos estás diciendo con qué DBMS estás trabajando, puede haber algunas diferencias sintácticas importantes para el caso que no estoy viendo. Las soluciones que te propongo con AMSI, es decir, planteadas desde el SQL estándar y deberían funcionar en (casi) todos los DBMS.

Tu consulta debería ser mas o menos así:
Código MySQL:
Ver original
  1.     `restaurantes` `t`  
  2.     INNER JOIN `serviciosrestaurantes` SR ON T.`id`= SR.`restaurantes_id`
  3.     INNER JOIN `servicios` S ON SR.`id`= S.`servicios_id`  
  4. WHERE S.id=1 OR S.id=2
o bien
Código MySQL:
Ver original
  1.     `restaurantes` `t`  
  2.     INNER JOIN `serviciosrestaurantes` SR ON T.`id`= SR.`restaurantes_id`
  3.     INNER JOIN `servicios` S ON SR.`id`= S.`servicios_id`  
  4. WHERE S.id IN(1, 2)

Dos cosas:
1) No nos dices qué framework crea esta sentencia, por lo que no podemos saber si es o no el adecuado, o siquiera si es bueno.
2) Un FMWK es tan bueno como el que lo programa.. lo cual desde la óptica de las bases de datos no suele ser una buena referencia. El 90% de las consultas creadas por medio de ellos deben ser modificadas para que realmente sean eficaces o eficientes.
__________________
¿A quién le enseñan sus aciertos?, si yo aprendo de mis errores constantemente...
"El problema es la interfase silla-teclado." (Gillermo Luque)
  #3 (permalink)  
Antiguo 30/05/2013, 08:27
 
Fecha de Ingreso: abril-2010
Mensajes: 298
Antigüedad: 14 años
Puntos: 1
Respuesta: Inner Join no devuelve nada

Gracias por tu respuesta gnzsoloyo,
Ya he entendido que esa condicion no es posible.
La sql me la genera Yii framework con el que desarrollo mis aplicaciones en PHP.

Te cuento un poco mas de informacion:

Tengo dos restaurantes vamos a poner que tienen ids 1 y 2.
Muy bien el restaurante id=1 tiene el servicio id=1( por ejemplo servicio de aparcacoches) y el restaurante id=2 tiene servicios con id=1 y id=2.(por ejemplo aparcacoche y guarderia...)

He probado tu sql:
Código MySQL:
Ver original
  1. FROM restaurantes AS T
  2. INNER JOIN serviciosrestaurantes AS SR ON T.id = SR.restaurantes_id
  3. INNER JOIN servicios AS S ON SR.id = S.id
  4. WHERE S.id =1
  5. OR S.id =2

Y me devuelve el restaurante de id=1 dado que cumple que tiene el servicio di=1 y obviamente no me devuelve el restaurante id=2 dado que tiene tanto el servicio con id=1 como el servicio con id=2.

Cual seria la SQL para obtener el restaurante que dispone de ambos servicios si es que este fuera posible???

Sino tendria que solucionarlo usando php?????

Gracias de nuevo!

Última edición por ferminako; 30/05/2013 a las 10:38
  #4 (permalink)  
Antiguo 30/05/2013, 13:14
Colaborador
 
Fecha de Ingreso: enero-2007
Ubicación: México
Mensajes: 2.097
Antigüedad: 17 años, 3 meses
Puntos: 447
Respuesta: Inner Join no devuelve nada

Hola ferminako:

Tengo algunos problemas para ver la imagen que colocaste en el post, pero creo haber entendido tu problema... en realidad este tipo de ejercicios es uno de los más recurrentes en SQL, hay muchos ejemplos en la red, o en este mismo foro... si te hubieras tomado un poco de tiempo estoy seguro de que habrías encontrado algo similar a lo que requieres, pero bueno, vayamos al grano... te pongo un script, supongamos que tienes las siguientes tablas:

Código MySQL:
Ver original
  1. mysql> SELECT * FROM restaurantes;
  2. +---------+--------------------+
  3. | id_rest | nombre_rest        |
  4. +---------+--------------------+
  5. |       1 | restaurante uno    |
  6. |       2 | restaurante dos    |
  7. |       3 | restaurante tres   |
  8. |       4 | restaurante cuatro |
  9. +---------+--------------------+
  10. 4 rows in set (0.16 sec)
  11.  
  12. mysql> SELECT * FROM servicios;
  13. +---------+---------------+
  14. | id_serv | nombre_serv   |
  15. +---------+---------------+
  16. |       1 | aparcacoches  |
  17. |       2 | guarderia     |
  18. |       3 | otro servicio |
  19. +---------+---------------+
  20. 3 rows in set (0.00 sec)
  21.  
  22. mysql> SELECT * FROM restaurantes_servicios;
  23. +--------------+---------+---------+
  24. | id_rest_serv | id_rest | id_serv |
  25. +--------------+---------+---------+
  26. |            1 |       1 |       1 |
  27. |            2 |       2 |       2 |
  28. |            3 |       3 |       1 |
  29. |            4 |       3 |       2 |
  30. |            5 |       4 |       1 |
  31. |            6 |       4 |       3 |
  32. +--------------+---------+---------+
  33. 6 rows in set (0.00 sec)

Supongo que esto es algo muy parecido a lo que tienes en tus tablas, observa que los restaurantes UNO y DOS tienen alguno de los servicios que tú necesitas, el restaurant TRES tiene ambos, y aunque el restaurante CUATRO tiene dos servicios SÓLO TIENE UNO DE LOS QUE TE INTERESAN. podrías hacer una consulta así:

Código MySQL:
Ver original
  1. mysql> SELECT id_rest, COUNT(DISTINCT id_serv)
  2.     -> FROM restaurantes_servicios WHERE id_serv IN (1, 2)
  3.     -> GROUP BY id_rest;
  4. +---------+-------------------------+
  5. | id_rest | COUNT(DISTINCT id_serv) |
  6. +---------+-------------------------+
  7. |       1 |                       1 |
  8. |       2 |                       1 |
  9. |       3 |                       2 |
  10. |       4 |                       1 |
  11. +---------+-------------------------+
  12. 4 rows in set (0.00 sec)

Observa que esta consulta te da el TOTAL DE SERVICIOS QUE TE INTERESA que tiene cada restaurant... OBSERVA QUE SÓLO EL RESTAURANT TRES tiene ambos servicios... agregando un HAVING COUNT() podrías filtrar aquellos que tengan ambos servicios:

Código MySQL:
Ver original
  1. mysql> SELECT id_rest
  2.     -> FROM restaurantes_servicios WHERE id_serv IN (1, 2)
  3.     -> GROUP BY id_rest
  4.     -> HAVING COUNT(DISTINCT id_serv) = 2;
  5. +---------+
  6. | id_rest |
  7. +---------+
  8. |       3 |
  9. +---------+
  10. 1 row in set (0.00 sec)

Esto es lo que necesitas para filtrar tu información... puedes hacerlo con INNER JOIN's y utilizar subconsultas, o utilizar las funciones IN o EXISTS... eso te lo dejo para tí.

Saludos
Leo.
  #5 (permalink)  
Antiguo 30/05/2013, 14:08
 
Fecha de Ingreso: abril-2010
Mensajes: 298
Antigüedad: 14 años
Puntos: 1
Respuesta: Inner Join no devuelve nada

Ok, muy interesante la clausula having, nunca sabia para que utilizarla...

Por ultimo , teniendo en cuenta que la consulta tambien va a contener la busqueda de tiposCocina q tiene la misma relacion que la de servicios, como podria hacerlo ? deberia usar el innerjoin anterior y el groupby y en el having incluir un 'and count(ditinct id_tipoCocina=...') que me has indicado o cual seria la mejor opcion?
  #6 (permalink)  
Antiguo 30/05/2013, 15:15
Colaborador
 
Fecha de Ingreso: enero-2007
Ubicación: México
Mensajes: 2.097
Antigüedad: 17 años, 3 meses
Puntos: 447
Respuesta: Inner Join no devuelve nada

Hola de nuevo ferminako:

Me sorprende que no hayas escuchado acerca de la cláusula HAVING, estos son conceptos básicos de SQL... creo que desde ahí estamos mal . Te recomiendo que comiences a leer cualquier libro para principiantes, pues estás tratando de correr cuando apenas y sabes gatear...

Hay que tener cuidado, pues estamos hablando de tablas distintas... en realidad la tabla de TIPOS DE COCINA POR RESTAURANT no tiene nada que ver con la tabla de SERVICIOS POR RESTAURANT, aunque estén relacionadas por el mismo restaurante (suena algo confuso, pero la idea es que un los servicios y los tipos de cocina no tienen una relación directa)

No podrías agregar una condición a la consulta anterior a menos que hicieras un LEFT o un RIGTH JOIN, cosa que podría complicar la consulta... te sugiero que hagas otra consulta aparte, la idea sería la misma:

Código MySQL:
Ver original
  1. SELECT id_rest, COUNT(DISTINCT id_tipoCocina)
  2. FROM restaurantes_tipos_cocina WHERE id_tipoCocina IN (1, 2)
  3. GROUP BY id_rest;

Ahora tienes por un lado los restaurantes que tienen los servicios que quieres y por otro lado los tipos de cocina que deseas... LA INTERSECCIÓN DE ESTOS DOS CONJUNTOS CUMPLIRÍAN CON TODAS LAS CONDICIONES...

Esto es cuestión de práctica, práctica, y más práctica... eso es lo que debes hacer... jugar con las consultas, intentar, preguntarle a SAN GOOGLE, buscar en este mismo foro... y si continuas con problemas, entonces postear algo de lo que intentaste hacer y decirnos con qué problemas te enfrentaste... esa es la única manera en que aprenderás a hacer estas consultas y otras mucho más complejas...

Saludos
Leo.
  #7 (permalink)  
Antiguo 31/05/2013, 00:05
 
Fecha de Ingreso: abril-2010
Mensajes: 298
Antigüedad: 14 años
Puntos: 1
Respuesta: Inner Join no devuelve nada

Finalmente lo he solucionado usando joins y combinando los in y el having tal que:
Código MySQL:
Ver original
  1. `restaurantes` `t`  LEFT OUTER JOIN `tiposcocinarestaurantes`
  2. `tiposCocina_tiposCocina` ON
  3. (`t`.`id`=`tiposCocina_tiposCocina`.`restaurantes_id`) LEFT OUTER JOIN
  4. `tiposCocina` `tiposCocina` ON
  5. (`tiposCocina`.`id`=`tiposCocina_tiposCocina`.`tiposCocina_id`)  LEFT OUTER
  6. JOIN `serviciosrestaurantes` `servicios_servicios` ON
  7. (`t`.`id`=`servicios_servicios`.`restaurantes_id`) LEFT OUTER JOIN
  8. `servicios` `servicios` ON
  9. (`servicios`.`id`=`servicios_servicios`.`servicios_id`)  WHERE (
  10. tiposCocina_id IN (1,2)) AND ( servicios_id IN (1,2)) GROUP BY t.id HAVING
  11. ( COUNT(DISTINCT tiposCocina_id)=2 and COUNT(DISTINCT servicios_id)=2)

Y funciona, por ultimo necesito tambien filtar por otra tabla más, esta tabla es disponibilidad y tiene un relacion 1 a n con restaurantes, es decir un restaurante puede tener una o más disponibilidades pero una disponibilidad es unica y exclusiva de un restaurante. He probado diversos joins pero no se cual es el correcto ni donde, donde lo pondrian ustedes?

Gracias!!

Última edición por ferminako; 05/06/2013 a las 03:01

Etiquetas: devuelve, join, nada, select, tabla
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 22:19.