MySQL - Comparar varios campos para obtener fecha mas reciente

 
Vista:
sin imagen de perfil
Val: 95
Ha mantenido su posición en MySQL (en relación al último mes)
Gráfica de MySQL

Comparar varios campos para obtener fecha mas reciente

Publicado por yaney (31 intervenciones) el 12/04/2018 17:02:42
Hola a todos

Tengo la siguiente consulta para listar registros cuyos campos de fecha al compararlos con la fecha de hoy hayan pasado 30 dias y menos de 40 días.

La tabla lo que hace es almacenar citas para hacer un determinado trabajo, donde a veces la cita se debe hacer en varias sesiones, por eso son 4 campos de fecha.
Si la cita se hizo en 2 sesiones, habrán dos campos fecha con datos, y dos campos fecha cuyo valor será 00-00-0000 porque no se llenaron, si se hizo en 4 sesiones, los 4 campos tendrán el dato de la fecha.

Debo obtener el campo de la última cita (que sería la fecha más reciente) y calcular que hayan pasado 30 días desde esa fecha

Qué función me permite obtener ese resultado?

mysql> SELECT appuntamento.num_ordine,cliente.cognome,cliente.nome,cliente.idcliente,DATEDIFF(appuntamento.sed1,Now())as sed1,DATEDIFF(appuntamento.sed2,Now())as sed2,DATEDIFF(appuntamento.sed3,Now())as sed3,DATEDIFF(appuntamento.sed4,Now())as sed4,DATE_FORMAT(appuntamento.sed1, '%d-%m-%Y') AS sed1a,DATE_FORMAT(appuntamento.sed2, '%d-%m-%Y') AS sed2a,DATE_FORMAT(appuntamento.sed3, '%d-%m-%Y') AS sed3a,DATE_FORMAT(appuntamento.sed4, '%d-%m-%Y') AS sed4a,appuntamento.remarketing FROM cliente inner join appuntamento on appuntamento.clienteid=cliente.idcliente where remarketing like 'si' AND ((DATEDIFF(Now(), appuntamento.sed1) >= 30 and DATEDIFF(Now(), appuntamento.sed1) <= 80) OR (DATEDIFF(Now(), appuntamento.sed2) >= 30 and DATEDIFF(Now(), appuntamento.sed2) <= 80) OR (DATEDIFF(Now(), appuntamento.sed3) >= 30 and DATEDIFF(Now(), appuntamento.sed3) <= 80) OR (DATEDIFF(Now(), appuntamento.sed4) >= 30 and DATEDIFF(Now(), appuntamento.sed4) <= 80)) order by operatore;
1
2
3
4
5
6
7
8
9
+------------+---------+-----------+-----------+------+------+------+------+------------+------------+------------+------------+-------------+
| num_ordine | cognome | nome      | idcliente | sed1 | sed2 | sed3 | sed4 | sed1a      | sed2a      | sed3a      | sed4a      | remarketing |
+------------+---------+-----------+-----------+------+------+------+------+------------+------------+------------+------------+-------------+
|        939 | uddin   | rakib     |       448 |  -69 |  -50 |  -43 |   -6 | 02-02-2018 | 21-02-2018 | 28-02-2018 | 06-04-2018 | si          |
|        937 | Gilli   | laura     |       752 |  -70 |  -44 |  -36 | NULL | 01-02-2018 | 27-02-2018 | 07-03-2018 | 00-00-0000 | si          |
|        934 | moretti | christian |       749 |  -38 | NULL | NULL | NULL | 05-03-2018 | 00-00-0000 | 00-00-0000 | 00-00-0000 | si          |
|        936 | vassura | matilde   |       751 |  -14 |  -31 | NULL | NULL | 29-03-2018 | 12-03-2018 | 00-00-0000 | 00-00-0000 | si          |
+------------+---------+-----------+-----------+------+------+------+------+------------+------------+------------+------------+-------------+
4 rows in set (0.00 sec)

Saludos y gracias
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
sin imagen de perfil
Val: 953
Oro
Ha mantenido su posición en MySQL (en relación al último mes)
Gráfica de MySQL

Comparar varios campos para obtener fecha mas reciente

Publicado por leonardo_josue (414 intervenciones) el 12/04/2018 17:37:00
Hola de nuevo yaney:

Desde mi punto de vista equivocaste el modelo de Datos, ya que si tienes una relación de 1 a muchos, lo correcto es que manejes la información a nivel de REGISTRO, no de columna. ¿Qué pasaría si el día mañana decides que no son 4 el número máximo de citas, sino 10? tendrías que agregar entonces 6 columnas. Además, tu tabla tampoco queda normalizada, ya que al poner con 0000-00-00 tantos campos es el equivalente a poner NULL's lo cual no debería de estar permitido. Entonces, la primer propuesta sería que cambies tu modelo:

En lugar de tener algo así:

1
2
3
4
5
6
7
8
9
mysql> SELECT * FROM tabla;
+------+------------+------------+------------+
| id   | fecha1     | fecha2     | fecha3     |
+------+------------+------------+------------+
|    1 | 2018-04-12 | 2018-04-10 | 0000-00-00 |
|    2 | 2018-04-01 | 0000-00-00 | 0000-00-00 |
|    3 | 2018-04-01 | 2018-04-19 | 2018-04-27 |
+------+------------+------------+------------+
3 rows in set (0.00 sec)

lo que deberías tener

1
2
3
4
5
6
7
8
9
10
11
12
mysql> SELECT id, fecha FROM tabla;
+------+------------+
| id   | fecha      |
+------+------------+
|    1 | 2018-04-12 |
|    1 | 2018-04-10 |
|    2 | 2018-04-01 |
|    3 | 2018-04-01 |
|    3 | 2018-04-19 |
|    3 | 2018-04-27 |
+------+------------+
9 rows in set (0.00 sec)

Entonces aquí no importa si el trabajo se realiza en 1, 2, 3, 100, 2000 o más citas, simplemente agregas tantos registros como citas tengas que realizar, SIN TENER QUE AGREGAR MÁS COLUMNAS al modelo. Además, este modelo no sólo es más eficiente, sino que te permitiría hacer consultas a tus datos de manera más sencilla, como por ejemplo saber el promedio de CITAS que tiene cada trabajo, el máximo de citas que tuvo un trabajo para poder realizarlo y más indicadores que te podrían servir.

Si puedes hacer el cambio HAZLO y evita dolores de cabeza en el futuro.

Ahora bien, si de plano no puedes cambiar el modelo (y esto implica que realmente tengas una razón de peso para no hacerlo) entonces puedes resolver tu problema de dos formas.

1. Utilizando la función GREATEST de MySQL, la cual te arroja el valor más grande de una colección de datos:

https://dev.mysql.com/doc/refman/5.7/en/comparison-operators.html


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
mysql> SELECT * FROM tabla;
+------+------------+------------+------------+
| id   | fecha1     | fecha2     | fecha3     |
+------+------------+------------+------------+
|    1 | 2018-04-12 | 2018-04-10 | 2018-04-08 |
|    2 | 2018-04-01 | 2018-04-19 | 2018-04-11 |
|    3 | 2018-04-01 | 2018-04-19 | 2018-04-27 |
+------+------------+------------+------------+
3 rows in set (0.00 sec)
 
mysql> SELECT id, GREATEST(fecha1, fecha2, fecha3) fecha_mas_reciente
    -> FROM tabla;
+------+--------------------+
| id   | fecha_mas_reciente |
+------+--------------------+
|    1 | 2018-04-12         |
|    2 | 2018-04-19         |
|    3 | 2018-04-27         |
+------+--------------------+
3 rows in set (0.00 sec)

La otra forma sería SIMULAR el modelo que te propongo al inicio de tener la información a nivel de RENGLON en lugar de a nivel de COLUMNAS y utilizar las funciones de agrupación propias de SQL, en este caso MAX (que según comentaste es lo que intentaste hacer), así:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
mysql> SELECT id, MAX(fecha) fecha_mas_reciente
    -> FROM
    -> ( SELECT id, fecha1 fecha FROM tabla
    ->   UNION ALL
    ->   SELECT id, fecha2 fecha FROM tabla
    ->   UNION ALL
    ->   SELECT id, fecha3 fecha FROM tabla ) T
    -> GROUP BY id;
+------+--------------------+
| id   | fecha_mas_reciente |
+------+--------------------+
|    1 | 2018-04-12         |
|    2 | 2018-04-19         |
|    3 | 2018-04-27         |
+------+--------------------+
3 rows in set (0.00 sec)

Observa que los UNION's Pasan tu información de nivel de columna a nivel de REGISTRO.

Haz la prueba y nos comentas y sobre todo, cambia tu modelo si puedes hacerlo.

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
2
Comentar
sin imagen de perfil
Val: 95
Ha mantenido su posición en MySQL (en relación al último mes)
Gráfica de MySQL

Comparar varios campos para obtener fecha mas reciente

Publicado por yaney (31 intervenciones) el 13/04/2018 09:57:17
Muchas gracias nuevamente Leonardo.

Tienes mucha razón en cuanto al modelo de base de datos, sé que debería hacer una tabla para las citas. En el futuro también arreglaré ese problemita (un futuro no muy lejano por eso de los NULL), por ahora tuve que hacerlo así pues me faltan conocimientos de otros lenguajes de programación, para poder hacer un formulario con subformulario (para las citas) y de este modo ingresar todos los datos a la base de datos, por tanto no me quedó más remedio que hacerlo de este modo que es hasta donde alcanzaban mis conocimientos hasta el momento. Pero sí, debo mejorar mi base de datos, pues a medida que voy estudiando también aprendo cosas que optimizan lo que al inicio hice con "novatadas". Hace un año me adentré en este mundo y realmente me gusta mucho, pero es infinito el conocimiento comparado con el tiempo de vida de un ser humano :D
Y bueno a lo nuestro...

Utilicé la función GREATEST como me indicas y finalmente quedó así:

mysql> SELECT cliente.idcliente,cliente.cognome,cliente.nome,cliente.cellulare,DATEDIFF(appuntamento.sed1,Now())as sed1,DATEDIFF(appuntamento.sed2,Now())as sed2,DATEDIFF(appuntamento.sed3,Now())as sed3,DATEDIFF(appuntamento.sed4,Now())as sed4,DATE_FORMAT(appuntamento.sed1, '%d-%m-%Y') AS sed1a,DATE_FORMAT(appuntamento.sed2, '%d-%m-%Y') AS sed2a,DATE_FORMAT(appuntamento.sed3, '%d-%m-%Y') AS sed3a,DATE_FORMAT(appuntamento.sed4, '%d-%m-%Y') AS sed4a,appuntamento.remarketing FROM cliente inner join appuntamento on appuntamento.clienteid=cliente.idcliente where remarketing like 'si' AND (DATEDIFF(Now(), GREATEST (appuntamento.sed1,appuntamento.sed2,appuntamento.sed3,appuntamento.sed4)) >= 30 and DATEDIFF(Now(), GREATEST (appuntamento.sed1,appuntamento.sed2,appuntamento.sed3,appuntamento.sed4)) <= 40) order by operatore;

1
2
3
4
5
6
7
8
+-----------+----------+------------+------------+------+------+------+------+------------+------------+------------+------------+-------------+
| idcliente | cognome  | nome       | cellulare  | sed1 | sed2 | sed3 | sed4 | sed1a      | sed2a      | sed3a      | sed4a      | remarketing |
+-----------+----------+------------+------------+------+------+------+------+------------+------------+------------+------------+-------------+
|       752 | Gilli    | laura      | 3317807340 |  -71 |  -45 |  -37 | NULL | 01-02-2018 | 27-02-2018 | 07-03-2018 | 00-00-0000 | si          |
|       749 | moretti  | christian  | 3347895905 |  -39 | NULL | NULL | NULL | 05-03-2018 | 00-00-0000 | 00-00-0000 | 00-00-0000 | si          |
|       766 | LICCARDI | Immacolata | 3924726479 |  -59 |  -31 | NULL | NULL | 13-02-2018 | 13-03-2018 | 00-00-0000 | 00-00-0000 | si          |
+-----------+----------+------------+------------+------+------+------+------+------------+------------+------------+------------+-------------+
3 rows in set (0.00 sec)

Obteniendo así la fecha la más reciente y a esta aplicándole el cálculo de mayor que 30 menos que 40 días transcurridos.

Gracias por tu explicación.
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