MySQL - Duda con consulta utilizando inner join

 
Vista:
Imágen de perfil de Roberto
Val: 1
Ha aumentado su posición en 3 puestos en MySQL (en relación al último mes)
Gráfica de MySQL

Duda con consulta utilizando inner join

Publicado por Roberto (1 intervención) el 21/06/2017 19:51:10
Les comento, tengo 2 tablas la primera se llama adicionales y la segunda se llama comandas.

En la tabla de adicionales mi diseño es de la siguiente manera:
Nombre Tipo
cveAdicional int (llave primaria)
descripción varchar
cveTipoAd int
precio double
fecha date
hora time
fehamod date
horamod time

Contenido de la tabla adicionales

adicionales

En la tabla de comandas mi diseño es de la siguiente manera:

Nombre Tipo
cveOrden int (llave primaria)
folio varchar
cveMenu int
cveMesa int
comentarios text
fecha date
hora time
status int
horacocina time
adic1 int
cantadic1 int
adic2 int
cantadic2 int
adic3 int
cantadic3 int
adic4 int
cantadic4 int
adic5 int
cantadic5 varchar


Contenido de la tabla comandas:

comandas

En mi tabla menus el contenido es el siguiente:
menus


Al realizar mi consulta tengo el siguiente codigo:

SELECT DISTINCT comandas.cveOrden, menus.titulo, menus.precio,
comandas.cveMesa, adicionales.descripcion, comandas.cantadic1, adicionales.descripcion,
comandas.cantadic2, adicionales.descripcion, comandas.cantadic3, adicionales.descripcion,
comandas.cantadic4, adicionales.descripcion, adicionales.descripcion, comandas.cantadic5
FROM comandas
INNER JOIN menus ON comandas.cveMenu = menus.cveMenu
INNER JOIN adicionales ON comandas.adic1 = adicionales.cveAdicional
OR comandas.adic2 = adicionales.cveAdicional
OR comandas.adic3 = adicionales.cveAdicional
WHERE comandas.cveOrden = 7;

El resultado que me muestra es este:

cveOrden titulo precio cveMesa descripcion cantadic1 descripcion1 cantadic2 descripcion2 cantadic3 descripcion3
7 Cena mexicana 90 4 Refresco 3 Refresco 2 Refresco 1 Refresco
7 Cena mexicana 90 4 Cerveza 3 Cerveza 2 Cerveza 1 Cerveza
7 Cena mexicana 90 4 Orden de aguacate 3 Orden de aguacate 2 Orden de aguacate 1 Orden de aguacate

Si se fijan el resultado me lo repite 3 veces y quisiera que solo me lo presentara en 1 fila

¿Se puede hacer esto?
Valora esta pregunta
Me gusta: Está pregunta es útil y esta claraNo me gusta: Está pregunta no esta clara o no es útil
0
Responder
Imágen de perfil de Stalin

Duda con consulta utilizando inner join

Publicado por Stalin (3 intervenciones) el 22/06/2017 15:25:19
Que tal Roberto podrías pasarme el script de tus tablas para replicarlo y probar pero te comento que puedes agregar al final un group by comandas.cveMenu; para que solo te muestre un registro prueba eso y me comentas.

Saludos.
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar
sin imagen de perfil
Val: 953
Oro
Ha mantenido su posición en MySQL (en relación al último mes)
Gráfica de MySQL

Duda con consulta utilizando inner join

Publicado por leonardo_josue (414 intervenciones) el 22/06/2017 17:01:17
Hola Roberto:

De entrada te comento que desde mi punto de vista tienes un mal diseño de tablas... cuando una entidad puede tener 1 o más atributos "iguales" como en el caso de los "tiempos" o los adicionales, no repites las columnas, sino que creas una nueva tabla y guardas la información a nivel de registro. Por ejemplo, con tus datos de los Menús y los tiempos, en lugar de tener una sola tabla con tiempo1, tiempo2, tiempo3, tiempo4, tiempo5, lo que haces es un modelo con TRES TABLAS, una para los MENÚS, otra para los TIEMPOS y otra que relacione AMBAS TABLAS:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
mysql> SELECT * FROM menus;
+---------+--------------------+
| id_menu | titulo             |
+---------+--------------------+
|       1 | Desayuno Campesino |
|       2 | Desayuno Campestre |
|       3 | Comida Poblana     |
+---------+--------------------+
3 rows in set (0.06 sec)
 
mysql> SELECT * FROM tiempos;
+-----------+---------------------+
| id_tiempo | descripcion         |
+-----------+---------------------+
|         1 | Café o leche        |
|         2 | Jugo o fruta        |
|         3 | Mantel de huevo     |
|         4 | Omellet de verduras |
|         5 | Sopa del día        |
|         6 | Arroz o Spagheti    |
|         7 | Enmoladas de pollo  |
+-----------+---------------------+
7 rows in set (0.00 sec)
 
mysql> SELECT * FROM menus_tiempos;
+----------------+---------+-----------+
| id_menu_tiempo | id_menu | id_tiempo |
+----------------+---------+-----------+
|              1 |       1 |         1 |
|              2 |       1 |         2 |
|              3 |       1 |         3 |
|              4 |       2 |         1 |
|              5 |       2 |         2 |
|              6 |       2 |         4 |
|              7 |       3 |         1 |
|              8 |       3 |         2 |
|              9 |       3 |         3 |
|             10 |       3 |         4 |
|             11 |       3 |         5 |
|             12 |       3 |         6 |
|             13 |       3 |         7 |
+----------------+---------+-----------+
13 rows in set (0.00 sec)

Aquí no importa si un menu se compone de 1 tiempo o de 50 tiempos... agregas tantos registros como sean necesarios, peor no hay desperdicio de campos.... en tu ejemplo, si un menu se compone de menos de 5 tiempos, entonces dejas los campos "sobrantes" en NULL, y ¿qué pasa si mañana quieres agregar más tiempos a un menú? pues que tendrías que agregar más columnas lo cual es absurdo...

Con el modelo de tres tablas, si quieres obtener qué tiempos conforman cada menú, en entonces lo puedes hacer por ejemplo con un GROUP_CONCAT así:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
mysql> SELECT
    ->   menus.id_menu,
    ->   menus.titulo,
    ->   GROUP_CONCAT(tiempos.descripcion) tiempos
    -> FROM menus_tiempos
    -> INNER JOIN menus ON menus.id_menu = menus_tiempos.id_menu
    -> INNER JOIN tiempos ON tiempos.id_tiempo = menus_tiempos.id_tiempo
    -> GROUP BY menus.id_menu, menus.titulo;
+---------+--------------------+------------------------------------------------------------------------------------------------------------------+
| id_menu | titulo             | tiempos                                                                                                          |
+---------+--------------------+------------------------------------------------------------------------------------------------------------------+
|       1 | Desayuno Campesino | Café o leche,Jugo o fruta,Mantel de huevo                                                                         |
|       2 | Desayuno Campestre | Café o leche,Jugo o fruta,Omellet de verduras                                                                    |
|       3 | Comida Poblana     | Sopa del día,Jugo o fruta,Omellet de verduras,Enmoladas de pollo,Mantel de huevo,Café o leche,Arroz o Spagheti   |
+---------+--------------------+------------------------------------------------------------------------------------------------------------------+
3 rows in set (0.00 sec)

¿Se entiende? si puedes cambiar tu modelo hazlo y evita dolores de cabeza futuros.

Ahora bien, si de plano no puedes cambiar tu modelo de tablas, entonces puedes tener problemas al utilizar condiciones OR en los JOIN's.... ya la unión se haría con tantos adicionales como existan, es por eso que da la impresión de que "repites" información. Este problema es típico con este tipo de modelos de tablas... NO PUEDES REPETIR adicionales.descripcion N veces y esperar que te regrese valores distintos. para resolver esto lo que haces es "duplicar" tu tabla de adicionales utilizando un ALIAS y haciendo un JOIN por cada adicional... voy a seguir retomando tu ejemplo de los menús:


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
mysql> SELECT * FROM tiempos;
+-----------+---------------------+
| id_tiempo | descripcion         |
+-----------+---------------------+
|         1 | Café o leche        |
|         2 | Jugo o fruta        |
|         3 | Mantel de huevo     |
|         4 | Omellet de verduras |
|         5 | Sopa del día        |
|         6 | Arroz o Spagheti    |
|         7 | Enmoladas de pollo  |
+-----------+---------------------+
7 rows in set (0.00 sec)
 
mysql> SELECT * FROM MENU_2;
+---------+--------------------+---------+---------+---------+
| id_menu | titulo             | tiempo1 | tiempo2 | tiempo3 |
+---------+--------------------+---------+---------+---------+
|       1 | Desayuno campestre |       1 |       2 |       3 |
|       3 | Desayuno otro      |       1 |       4 |    NULL |
|       2 | Desayuno uno mas   |       5 |    NULL |    NULL |
+---------+--------------------+---------+---------+---------+
3 rows in set (0.00 sec)

Para obtener la descripción de cada tiempo, de entrada NO PUEDO HACER INNER JOIN'S porque hay campos que traen NULL, por lo tanto debo utilizar LEFT JOIN, segundo, NO PUEDO UTILIZAR UNA SOLA TABLA DE TIEMPOS, porque estamos hablando de tiempos DISTINTOS, entonces lo que hago es "duplicar" la tabla de tiempos y utilizar ALIAS distintos

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
mysql> SELECT
    ->   menu_2.titulo,
    ->   t1.descripcion primer_tiempo,
    ->   t2.descripcion segundo_tiempo,
    ->   t3.descripcion tercer_tiempo
    -> FROM menu_2
    -> LEFT JOIN tiempos t1 ON T1.id_tiempo = menu_2.tiempo1
    -> LEFT JOIN tiempos t2 ON T2.id_tiempo = menu_2.tiempo2
    -> LEFT JOIN tiempos t3 ON T3.id_tiempo = menu_2.tiempo3;
+--------------------+---------------+---------------------+-----------------+
| titulo             | primer_tiempo | segundo_tiempo      | tercer_tiempo   |
+--------------------+---------------+---------------------+-----------------+
| Desayuno campestre | Café o leche  | Jugo o fruta        | Mantel de huevo |
| Desayuno otro      | Café o leche  | Omellet de verduras | NULL            |
| Desayuno uno mas   | Sopa del día  | NULL                | NULL            |
+--------------------+---------------+---------------------+-----------------+
3 rows in set (0.00 sec)

Entonces, en lugar de usar OR en la cláusula ON, se tiene que hacer un JOIN's por cada tiempo, ¿se entiende?

Haz la prueba y nos comentas.

Saludos
Leo.
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
1
Comentar