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

Consulta 1 a m

Estas en el tema de Consulta 1 a m en el foro de Bases de Datos General en Foros del Web. (el asunto sería Consulta n a m) Hola, A ver si me explico bien: Tengo 2 tablas (Ta y Tb) con una relación n a ...
  #1 (permalink)  
Antiguo 04/08/2011, 06:14
igg
 
Fecha de Ingreso: agosto-2011
Mensajes: 4
Antigüedad: 12 años, 8 meses
Puntos: 0
Consulta 1 a m

(el asunto sería Consulta n a m)
Hola,

A ver si me explico bien:

Tengo 2 tablas (Ta y Tb) con una relación n a m y quiero obtener todos los datos tanto de Ta como de Tb, al poner un criterio de búsqueda sobre Tb lógicamente me devuelve los datos de Ta y Tb que cumplen ese criterio, pero lo que yo quiero son también el resto de datos de Tb que tienen relación con los devueltos de Ta.

Se que se puede hacer con una subquery que obtenga los id's de Ta con ese criterio y una select con todos (Ta y Tb) con un in de los id's de la subquery, pero tengo el problema del número de resultados de la subquery que puede ser muy alto y ralentizarme la consulta. ¿Se podría hacer de otra forma?

Voy a poner un ejemplo con la solución que conozco pero que no me gusta para ver si queda más claro:
select Ta.id, Ta.nombre, Tb.id, Tb.nombre
form Ta join Tr on Ta.id = Tr.idTa join Tb on Tr.idTb = Tb.id
where Ta.id in (select Ta.id
form Ta join Tr on Ta.id = Tr.idTa join Tb on Tr.idTb = Tb.id
where Tb.id = 23)
Esto devolvería pej:
  • 1 Nombre1 23 Nombre23
  • 1 Nombre1 24 Nombre24
  • 3 Nombre3 23 Nombre23
  • 3 Nombre3 25 Nombre25
  • 3 Nombre3 27 Nombre27
  • 8 Nombre8 23 Nombre23

Espero que entendáis lo que intento preguntar, muchas gracias

Última edición por igg; 04/08/2011 a las 06:29
  #2 (permalink)  
Antiguo 04/08/2011, 07:26
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, 5 meses
Puntos: 2658
Respuesta: Consulta 1 a m

Si tienes una relación N:N entre dos tablas, entonces no tienes dos tablas. Deberías tener una tercera tabla ,que sea la que contenga y administre esa relación.
Sólo se puede dar una relación N:N de dos tablas si la relación es N:N de una tabla consigo misma.
Hay algo mal en tu planteo. ¿Podrías explicar un poco mejor de qué se trata la relación que hay entre esas dos tablas?
__________________
¿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 05/08/2011, 06:01
igg
 
Fecha de Ingreso: agosto-2011
Mensajes: 4
Antigüedad: 12 años, 8 meses
Puntos: 0
Respuesta: Consulta 1 a m

Efectivamente son 3 las tablas pero como la 3ª es la relación pues no lo he especificado, fallo mio.

Un saludo
  #4 (permalink)  
Antiguo 05/08/2011, 06:55
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, 5 meses
Puntos: 2658
Respuesta: Consulta 1 a m

Necesitas usar la tercera como nexo, o la consulta no funcionará.
__________________
¿A quién le enseñan sus aciertos?, si yo aprendo de mis errores constantemente...
"El problema es la interfase silla-teclado." (Gillermo Luque)
  #5 (permalink)  
Antiguo 08/08/2011, 03:30
igg
 
Fecha de Ingreso: agosto-2011
Mensajes: 4
Antigüedad: 12 años, 8 meses
Puntos: 0
Respuesta: Consulta 1 a m

Hola,

Si te fijas en el ejemplo que pongo, podrás ver la tercera tabla, la de relación (Tr). De todas formas, como comento, no digo que no me funcione sino si se puede hacer de otra forma al ejemplo que pongo.

Gracias y un saludo.
  #6 (permalink)  
Antiguo 08/08/2011, 05:22
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, 5 meses
Puntos: 2658
Respuesta: Consulta 1 a m

Cita:
Iniciado por igg Ver Mensaje
Hola,

Si te fijas en el ejemplo que pongo, podrás ver la tercera tabla, la de relación (Tr). De todas formas, como comento, no digo que no me funcione sino si se puede hacer de otra forma al ejemplo que pongo.

Gracias y un saludo.
La tercera tabla, en una relación N:N es mandatoria. Si la pudieras eliminar la relación sería 1:N.

Fuera de eso, la mejor escritura de una relación N:N es la ortodoxa:
Código MySQL:
Ver original
  1. SELECT Ta.id, Ta.nombre, Tb.id, Tb.nombre
  2.     Ta INNER JOIN Tr ON Ta.id = Tr.idTa
  3.     INNER JOIN Tb ON Tr.idTb = Tb.id
  4. WHERE Tb.id = 23;
Si te fijas con cuidado, el la subconsulta es redundante respecto a la consulta mayor. Carece de sentido porque devolverán lo mismo. Al menos para el ejemplo que pones, quitar ese subselect es lo mismo que ponerlo.
__________________
¿A quién le enseñan sus aciertos?, si yo aprendo de mis errores constantemente...
"El problema es la interfase silla-teclado." (Gillermo Luque)
  #7 (permalink)  
Antiguo 09/08/2011, 01:40
igg
 
Fecha de Ingreso: agosto-2011
Mensajes: 4
Antigüedad: 12 años, 8 meses
Puntos: 0
Respuesta: Consulta 1 a m

Creo que no, creo que si no pones la subselect solo te traerías:
  • 1 Nombre1 23 Nombre23
  • 3 Nombre3 23 Nombre23
  • 8 Nombre8 23 Nombre23

Faltarían aquellos de Tb que no cumplen el where pero que estan relacionados con Ta y que con la subselect sí que te saldrían.

Pongo el código de mi ejemplo y las dos selects:

Código:
CREATE TABLE Ta (ID NUMBER(2), NOMBRE VARCHAR2(10));

CREATE TABLE Tb (ID NUMBER(2), NOMBRE VARCHAR2(10));

CREATE TABLE Tr (idTa NUMBER(2), idTb NUMBER(2));

INSERT INTO Ta (ID, NOMBRE) VALUES (1, 'N_1');
INSERT INTO Ta (ID, NOMBRE) VALUES (2, 'N_2');
INSERT INTO Ta (ID, NOMBRE) VALUES (3, 'N_3');
INSERT INTO Ta (ID, NOMBRE) VALUES (8, 'N_8');

INSERT INTO Tb (ID, NOMBRE) VALUES (23, 'N_23');
INSERT INTO Tb (ID, NOMBRE) VALUES (24, 'N_24');
INSERT INTO Tb (ID, NOMBRE) VALUES (25, 'N_25');
INSERT INTO Tb (ID, NOMBRE) VALUES (27, 'N_27');
INSERT INTO Tb (ID, NOMBRE) VALUES (28, 'N_28');

INSERT INTO Tr (idTa, idTb) VALUES (1, 23);
INSERT INTO Tr (idTa, idTb) VALUES (1, 24);
INSERT INTO Tr (idTa, idTb) VALUES (2, 24);
INSERT INTO Tr (idTa, idTb) VALUES (2, 28);
INSERT INTO Tr (idTa, idTb) VALUES (3, 23);
INSERT INTO Tr (idTa, idTb) VALUES (3, 25);
INSERT INTO Tr (idTa, idTb) VALUES (3, 27);
INSERT INTO Tr (idTa, idTb) VALUES (8, 23);

select Ta.id, Ta.nombre, Tb.id, Tb.nombre
from Ta inner join Tr on Ta.id = Tr.idTa inner join Tb on Tr.idTb = Tb.id
where Ta.id in (select Ta.id
    from Ta inner join Tr on Ta.id = Tr.idTa inner join Tb on Tr.idTb = Tb.id
    where Tb.id = 23)
    
select Ta.id, Ta.nombre, Tb.id, Tb.nombre
from Ta inner join Tr on Ta.id = Tr.idTa inner join Tb on Tr.idTb = Tb.id
where Tb.id = 23
En la primera select devuelve 6 filas mientras que la segunda solo 3, lo que necesito es saber si existe una forma de hacer una select que devuelva lo que la primera pero sin usar la subselect ni el in por problemas de rendimiento y evitar errores por sobrecargar el in ya que pueden salir mas de 1000 resultados.

Gracias.

Etiquetas: sql, bases-de-datos
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 18:17.