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

Cómo consigo esto?

Estas en el tema de Cómo consigo esto? en el foro de Mysql en Foros del Web. Hola, tengo un problema de bases de datos con MySQL, a ver si me pudiérais ayudar: Tengo dos tablas, distribuidas de esta forma: tabla 1 ...
  #1 (permalink)  
Antiguo 08/12/2011, 05:16
 
Fecha de Ingreso: noviembre-2011
Mensajes: 2
Antigüedad: 12 años, 5 meses
Puntos: 0
Cómo consigo esto?

Hola,
tengo un problema de bases de datos con MySQL, a ver si me pudiérais ayudar:
Tengo dos tablas, distribuidas de esta forma:

tabla 1
Nif Nombre
3232 Luis
1232 Paco
1242 Juan

tabla 2
Nif Rasgo Tipo
3232 Pelo Rubio
3232 Ojos Azules
3232 Altura 180
3232 Especial Lunares
1232 Pelo Rubio
1232 Ojos Marrones
1232 Altura 180
2324 Pelo Moreno
2324 Ojos Azules
2324 Altura 150

Y necesito obtener esto:

Nif Nombre Pelo Ojos Altura Especial
3232 Luis
1232 Paco
1242 Juan

Estoy utilizando LEFT OUTER JOIN, utilizando varias veces la tabla 2, y filtrando por el rasgo, algo así:
SELECT * FROM tabla1 LEFT OUTER JOIN tabla2 t2_1 ON tabla1.Nif=t2_1.Nif LEFT OUTER JOIN tabla2 t2_2 ON tabla1.Nif=t2_2.Nif
LEFT OUTER JOIN tabla2 t2_3 ON tabla1.Nif=t2_3.Nif LEFT OUTER JOIN tabla2 t2_4 ON tabla1.Nif=t2_4.Nif
WHERE t2_1.Rasgo=Pelo t2_2.Rasgo=Ojos t2_3.Rasgo=Altura

Y aquí viene mi problema, si pongo t2_4.Rasgo=Especial , sólo me va a salir la línea de la persona con un rasgo especial, y si no pongo nada,
se me multiplican las líneas de la consulta...
Una solución sería añadir el rasto "Especial" a todas las personas, pero esto me aumentará el número de líneas de la tabla muchísimo, y perderé
rapidez de búsqueda.

¿Se os ocurre otra forma de plantear la consulta para que salga bien sin tener que añadir el rasgo especial en blanco a todos los indivídulos?

Muchas gracias.
  #2 (permalink)  
Antiguo 08/12/2011, 08:51
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: Cómo consigo esto?

Tal y como están armadas las tablas, resulta en consultas algo complicadas como la que has planteado, y con una tendencia a generar productos cartesianos. El problema básico es que, a menos que se trate de un ejercicio de la asignatura Bases de Datos, el modelo planteado en dos tablas no sólo es ineficiente, no respeta el paradigma E-R.
Me explico: Estás atomizando una entidad que define a una persona, pero al hacerlo estás separando atributos que le son propios en una tabla secundaria, donde estás mezclando atributos de diferentes clases de dominio. Eso es incorrecto.
Si la persona siempre tendrá ojos, pelo y piel, esos atributos no se deben separar de la entidad que representa a la misma. Son propiedades de la clase o entidad.
Lo que si puedes hacer es crear una entidad distinta que permita manejar una clasificación para un atributo determinado, especialmente cuando ese atributo sólo contenga un numero acotado de variaciones posible, como es el caso del color de ojos, del color de piel o del tipo y color de pelo.
Además, y principalmente, con ello evitas la repetición de valores en el registro, y la posibilidad de errores de tipeo al ingresar valores similares. Tu esquema, por ejemplo, no previene que se ingrese ("Pelo", "Azul") o bien ("Ojos", "Azles"), por ejemplo.
Si separas esas instancias en tablas diferentes donde cada cosa sea única, el JOIN necesario para crear tu consulta será mucho más sencillo.
En otras palabras:
La tabla 1 debería tener por atributos: (nombre, altura, cabello_id, piel_id, ojos_id, otros_rasgos_id)
La tabla 2 debería ser descompuesta en entidades base, tales como Cabello(cabello_id, desc_color); Ojos(ojos_id, desc_color) y Otros_Rasgos(otros_rasgos_id, descripcion);
La altura no es necesario hacerlo por dos razones: 1) Todo ser tiene una altura física, por lo tanto no es algo opcional o nulificable; 2) No existen rangos acotados, por lo que poner todas las alturas posible requeriría más espacio de disco que la cantidad de personas en la primera tabla.
En ese contexto, crear la sentencia de consulta sería bastante simple:
Código MySQL:
Ver original
  1. SELECT Nif, Nombre,  C.altura, C.desc_color Cabello, O.desc_color, GROUP_CONCAT(R.descripcion) Otros
  2.     tabla1 P
  3.     LEFT JOIN Cabello C ON P.cabello_id = C.cabello_id
  4.     LEFT JOIN Ojos O ON P.ojos_id = O.ojos_id
  5.     LEFT JOIN Otros_Rasgos R ON P.otros_rasgos_id = R.otros_rasgos_id
  6. GROUP BY P.Nif;

Ahora bien, si aún así insistes en usar tu esquema, la idea más aproximada sería:
Código MySQL:
Ver original
  1.     Nif,
  2.     Nombre,
  3.     CONCAT(T1.Rasgo, ' ', T1.Tipo) Pelo,
  4.     CONCAT(T2.Rasgo, ' ', T2.Tipo) Ojos,
  5.     CONCAT(T3.Rasgo, ' ', T3.Tipo) Altura,
  6.     GROUP_CONCAT(CONCAT(T4.Rasgo, ' ', T4.Tipo)) Especial
  7.     tabla1 T
  8.     LEFT JOIN tabla2 T1 ON tabla1.Nif = T1.Nif
  9.     LEFT JOIN tabla2 T2 ON tabla1.Nif = T2.Nif
  10.     LEFT JOIN tabla2 T3 ON tabla1.Nif = T3.Nif
  11.     LEFT JOIN tabla2 T4 ON tabla1.Nif = T4.Nif
  12.     T1.Rasgo ='Pelo'
  13.     OR
  14.     T2.Rasgo = 'Ojos'
  15.     OR
  16.     T3.Rasgo = 'Altura'
  17.     OR
  18.     T4.Rasgo = 'Especial'
  19. GROUP BY T.Nif;
__________________
¿A quién le enseñan sus aciertos?, si yo aprendo de mis errores constantemente...
"El problema es la interfase silla-teclado." (Gillermo Luque)

Etiquetas: select
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 08:06.