MySQL - inner, join o union???

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

inner, join o union???

Publicado por kike (7 intervenciones) el 10/06/2017 10:24:08
Tengo una tabla de clientes con
Id_cli Nom_cli

1 PEREZ LOYOLA JUAN
2 LIZARRAGA UGAZ PEDRO

Tengo una tabla de historial con
Id_cli ano mes

1 2015 1
1 2016 3
1 2016 7
2 2016 2
2 2017 3
2 2017 5

Deseo mostrar
Id_cli Nom_cli ano mes
1 PEREZ LOYOLA JUAN 2016 7
2 LIZARRAGA UGAZ PEDRO 2017 5

cual seria la consulta para anidar al cliente CON SU ULTIMO REGISTRO EN EL HISTORIAL???
agradezco de antemano sus aportes... un abrazo
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 [abZeroX]
Val: 42
Ha aumentado su posición en 2 puestos en MySQL (en relación al último mes)
Gráfica de MySQL

inner, join o union???

Publicado por [abZeroX] (11 intervenciones) el 11/06/2017 00:22:06
Hola prueba con esto:

1
2
3
4
5
6
7
SELECT c.Id_cli, c.Nom_cli, h.ano, h.mes
FROM clientes as c
INNER JOIN (
	SELECT Id_cli, MAX(ano) AS ano, MAX(mes) AS mes
	FROM historial
	GROUP BY Id_cli
) AS h ON c.Id_cli = h.Id_cli;

Nos comentas.
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
2
Comentar
Imágen de perfil de kip
Val: 98
Bronce
Ha mantenido su posición en MySQL (en relación al último mes)
Gráfica de MySQL

inner, join o union???

Publicado por kip (30 intervenciones) el 11/06/2017 01:23:03
Hola, el codigo de abZeroX es el correcto en el contexto de relacionar las dos tablas, pero fallaria si tu ingresaras otro valor a historial como por ejemplo:

1
2
3
4
5
6
7
8
9
10
11
12
13
mysql> SELECT * FROM historial;
+--------+------+-----+
| Id_cli | ano  | mes |
+--------+------+-----+
|      1 | 2016 |   1 |
|      1 | 2016 |   3 |
|      1 | 2016 |   7 |
|      2 | 2016 |   2 |
|      2 | 2017 |   3 |
|      2 | 2017 |   5 |
|      1 | 2017 |   1 |
+--------+------+-----+
7 rows in set

He agregado ese ultimo registro y veamos como funcionaria con el codigo que te postearon mas arriba:

1
2
3
4
5
6
7
+--------+----------------------+------+-----+
| Id_cli | Nom_cli              | ano  | mes |
+--------+----------------------+------+-----+
|      1 | PEREZ LOYOLA JUAN    | 2017 |   7 |
|      2 | LIZARRAGA UGAZ PEDRO | 2017 |   5 |
+--------+----------------------+------+-----+
2 rows in set

Parece que el segundo cliente lo muestra perfectamente, pero que pasa con el primero ? Si nos fijamos toma como maximo el 2017 que esta bien ya que este es el mayor pero tambien toma el 7 que tecnicamente esta bien pero este no es el mes mayor en relación al año mayor que se muestra!

Esto sucede porque se selecciona independientemente cada valor, año y mes, mi recomendacion seria que si no puedes modificar la tabla para tener en lugar de dos campos año y mes separados uno solo que sea de tipo DATE, uses alguna funcion para tomar estos dos valores y evaluarlos como un valor tipo DATE, para eso existe STR_TO_DATE, pero debes recordar que en tu caso al no tener dias, debes quitar el valor en la variable global sql_mode de NO_ZERO_IN_DATE.

Entonces quedaria algo asi:

Primero seteamos el sql_mode para que funcione correctamente la funcion STR_TO_DATE con valores 0 en el retorno:
1
2
mysql> SET sql_mode = '';
Query OK, 0 rows affected

Luego usando la misma logica de relacion de datos pero cambiando la query obtenemos los valores adecuados:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
mysql> SELECT
	c.id_cli,
	c.nom_cli,
	DATE_FORMAT(h.fecha, '%Y-%m') AS fecha
FROM	clientes AS c
INNER JOIN (
	SELECT
		id_cli,
		MAX(STR_TO_DATE(CONCAT(ano, '-', mes),'%Y-%m')) AS fecha
	FROM
		historial
	GROUP BY
		id_cli
) AS h ON c.id_cli = h.id_cli;
+--------+----------------------+---------+
| id_cli | nom_cli              | fecha   |
+--------+----------------------+---------+
|      1 | PEREZ LOYOLA JUAN    | 2016-07 |
|      2 | LIZARRAGA UGAZ PEDRO | 2017-05 |
+--------+----------------------+---------+
2 rows in set

Probemos añadiendo el valor que mencionaba al inicio:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
mysql> SELECT
	c.id_cli,
	c.nom_cli,
	DATE_FORMAT(h.fecha, '%Y-%m') AS fecha
FROM	clientes AS c
INNER JOIN (
	SELECT
		id_cli,
		MAX(STR_TO_DATE(CONCAT(ano, '-', mes),'%Y-%m')) AS fecha
	FROM
		historial
	GROUP BY
		id_cli
) AS h ON c.id_cli = h.id_cli;
+--------+----------------------+---------+
| id_cli | nom_cli              | fecha   |
+--------+----------------------+---------+
|      1 | PEREZ LOYOLA JUAN    | 2017-01 |
|      2 | LIZARRAGA UGAZ PEDRO | 2017-05 |
+--------+----------------------+---------+
2 rows in set

Mas info: https://dev.mysql.com/doc/refman/5.7/en/date-and-time-functions.html#function_str-to-date
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
2
Comentar
Imágen de perfil de kike
Val: 10
Ha aumentado su posición en 5 puestos en MySQL (en relación al último mes)
Gráfica de MySQL

inner, join o union???

Publicado por kike (7 intervenciones) el 12/06/2017 18:46:00
Para abZeroX y Kip mis agradecimiento por sus soluciones me sirvió de maravilla y amplió mis conocimientos !!!!! MUCHAS GRACIAS!!!
Un abrazo.
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