
Trabajando en un proyecto durante el fin de semana, me familiaricé con la clave SQL «LATERAL», que no había usado antes, porque se introdujo recientemente en MySQL 8.0.14, así que quería compartir cómo se puede usar.
Algunas referencias sobre este tema:
Tablas auxiliares de derivadas
Tablas de derivadas SIDE en MySQL 8.0
La tecla «LATERAL» entra en juego cuando se trabaja con tablas derivadas. Las tablas derivadas han estado disponibles en MySQL durante mucho tiempo y se ven así esquemáticamente:
SELECCIONE t1.foo, t2.bar DESDE t1, (SELECCIONE barra DESDE table2 DONDE
SELECCIONE t1.fou, t2.bar SÍ t1, (SELECCIONE bar SÍ Tabla 2 INDUNI <condición> ) t2 INDUNI t1.identificación=t2.identificación; |
la mesa «
(SELECCIONE bar SÍ tabla 1 INDUNI <condición> ) t2”Se usa en la condición FROM es una tabla derivada, y puede unir tablas regulares y derivadas normalmente.
Las tablas derivadas generalmente se ejecutan como materializadas (UNA VEZ por solicitud y se almacenan como «almacenadas en caché» en las tablas de tiempo) o a través de una tabla externa.
Entonces, ¿cuál es el problema con las tablas de derivadas? Encontrará una limitación cuando intente utilizar una condición en una tabla derivada que haga referencia a una tabla externa. Por ejemplo:
SELECCIONE t1.foo, t2.bar DESDE t1, (SELECCIONE barra DESDE table2 DONDE
SELECCIONE t1.fou, t2.bar SÍ t1, (SELECCIONE bar SÍ Tabla 2 INDUNI <condición> Y Tabla 2.datos=t1.datos ) t2 INDUNI t1.identificación=t2.identificación; |
Esto no está permitido, y para usar esta aplicación necesita especificar una palabra clave LATERAL, por lo que la pregunta será como:
SELECCIONE t1.foo, t2.bar DESDE t1, LATERAL (SELECCIONE barra DESDE table2 DONDE
SELECCIONE t1.fou, t2.bar SÍ t1, LADO (SELECCIONE bar SÍ Tabla 2 INDUNI <condición> Y Tabla 2.datos=t1.datos ) t2 INDUNI t1.identificación=t2.identificación; |
¿Qué es un inconveniente? Bueno, la solicitud derivada no se puede ejecutar ahora una vez por solicitud y se ejecutará PARA CADA fila de la tabla t1, por lo que obviamente viene con una penalización de rendimiento y debe usarse con cuidado.
Quizás se esté preguntando, entonces, ¿cuándo necesitamos usar LATERAL como lo hacíamos mucho antes de MySQL 8.0.14?
De hecho, llegué a esta pregunta que funciona con series temporales y pronósticos (datos de pronóstico). Por ejemplo, para cada día, tenemos una predicción métrica para cada uno de los 30 días siguientes.
Por ejemplo
Fecha pronóstico |
Datos en el futuro |
Pronóstico métrico |
28/03/2020 |
29/03/2020 |
5 |
28/03/2020 |
30/03/2020 |
8 |
28/03/2020 |
31/03/2020 |
10 |
… 27 filas más para el 28/03/2020 |
⁇ |
|
29/03/2020 |
30/03/2020 |
3 |
29/03/2020 |
31/03/2020 |
7 |
29/03/2020 |
01/04/2020 |
4 |
… 27 filas más para el 29/03/2020 |
Para cada fecha de predicción en la tabla, necesito encontrar la predicción métrica SOLAMENTE para el día siguiente.
Probablemente hay varias formas de escribir esta pregunta, y también traté de abordar esto en la aplicación, pero con la tabla derivada LATERAL puede escribir esto como:
SELECCIONE * FROM tabla_predicción q, LATERAL (SELECCIONE fecha_en_futuro, DATEDIFF (fecha_en_futuro, fecha_predicción) df FROM tabla_predicción q1 WHERE q1.date_prediction = q.date_prediction ORDEN POR df ASC LIMIT 1) q2 WHERE q2.qdut;
SELECCIONE * SÍ tabla_prediccion q , LADO ( SELECCIONE datos_en_el_futuro,FECHADIFF(datos_en_el_futuro, predicción_fecha) d.f. SÍ tabla_prediccion q1 INDUNI q1.predicción_fecha=q.predicción_fecha PEDIDO POR d.f. ASC LÍMITE 1) q2 INDUNI q2.fecha_en_el_futuro=q.fecha_en_el_futuro; |
Y si no lo necesita exactamente mañana, sino para N días, puede usar la función VENTANA
RANGO() ENCIMA ( PEDIDO POR FECHADIFF(fecha de vencimiento,fecha de negociación)) r.
Entonces la pregunta es:
SELECCIONE * DESDE tabla_predicción q, LATERAL (SELECCIONE fecha_en_futuro, RANGO () SOBRE (ORDENAR POR FECHADIFF (vencimiento, fecha de negociación)) r DESDE tabla_predicción q1 DONDE q1.fecha_predicción = q.fecha_predicción) q2 DONDE q2.fecha_en_futuro NORTE;
SELECCIONE * SÍ tabla_prediccion q , LADO ( SELECCIONE datos_en_el_futuro,RANGO() ENCIMA ( PEDIDO POR FECHADIFF(fecha de vencimiento,fecha de negociación)) r SÍ tabla_prediccion q1 INDUNI q1.predicción_fecha=q.predicción_fecha) q2 INDUNI q2.fecha_en_el_futuro=q.fecha_en_el_futuro Y r=norte; |
Estoy feliz de ver que MySQL 8 viene con un nuevo y completo conjunto de funciones de SQL, lo que hace que trabajar con consultas sea mucho más fácil.