una soporta segundo rapida por optimizar mas lentas lenta hacer cuantas consultas consulta con como mysql sql sliding-window

soporta - optimizar consultas lentas mysql



Simular la funciĆ³n de retardo en MySQL (3)

| time | company | quote | +---------------------+---------+-------+ | 0000-00-00 00:00:00 | GOOGLE | 40 | | 2012-07-02 21:28:05 | GOOGLE | 60 | | 2012-07-02 21:28:51 | SAP | 60 | | 2012-07-02 21:29:05 | SAP | 20 |

¿Cómo hago un retraso en esta tabla en MySQL para imprimir la diferencia entre comillas, por ejemplo:

GOOGLE | 20 SAP | 40


Desde MySQL 8.0 y superior no hay necesidad de simular LAG . Es nativamente compatible,

Función de ventana :

Devuelve el valor de expr de la fila que retrasa (precede) la fila actual en N filas dentro de su partición. Si no existe dicha fila, el valor de retorno es el predeterminado. Por ejemplo, si N es 3, el valor de retorno es el predeterminado para las primeras dos filas. Si falta N o valor predeterminado, los valores predeterminados son 1 y NULL, respectivamente.

SELECT company, quote, LAG(quote) OVER(PARTITION BY company ORDER BY time) AS prev_quote FROM tab;

DBFiddle Demo


Este es mi truco MySQL favorito.

Así es como se emula la función de retraso:

SET @quot=-1; select time,company,@quot lag_quote, @quot:=quote curr_quote from stocks order by company,time;

  • lag_quote contiene el valor de la cita de la fila anterior. Para la primera fila @quot es -1.
  • curr_quote contiene el valor de la cita de la fila actual.

Notas:

  1. order by cláusula es importante aquí al igual que en una función de ventana normal.
  2. También es posible que desee utilizar lag para la company solo para asegurarse de que está calculando la diferencia en las cotizaciones de la misma company .
  3. También puede implementar contadores de fila de la misma manera @cnt:=@cnt+1

Lo bueno de este esquema es que es computacionalmente muy delgado en comparación con algunos otros enfoques, como el uso de funciones agregadas, procedimientos almacenados o procesamiento de datos en el servidor de aplicaciones.

EDITAR:

Ahora viene su pregunta de obtener el resultado en el formato que mencionó:

SET @quot=0,@latest=0,company=''''; select B.* from ( select A.time,A.change,IF(@comp<>A.company,1,0) as LATEST,@comp:=A.company as company from ( select time,company,quote-@quot as change, @quot:=quote curr_quote from stocks order by company,time) A order by company,time desc) B where B.LATEST=1;

La anidación no está relacionada, por lo que no es tan mala (computacionalmente) como parece (sintácticamente) :)

Avíseme si necesita ayuda con esto.


Para lograr el resultado deseado, primero debe encontrar la última y la próxima marca de tiempo para cada compañía. Es bastante simple con la siguiente consulta:

SELECT c.company, c.mts, max(l.ts) AS lts FROM (SELECT company, max(ts) AS mts FROM cq GROUP BY company) AS c LEFT JOIN cq l ON c.company = l.company AND c.mts > l.ts GROUP BY c.company, c.mts;

Ahora debe unirse a esta subconsulta con la tabla original para obtener los resultados deseados:

SELECT c.company, l.quote, coalesce(l1.quote, 0), (l.quote - coalesce(l1.quote, 0)) AS result FROM (SELECT c.company, c.mts, max(l.ts) AS lts FROM (SELECT company, max(ts) AS mts FROM cq GROUP BY company) AS c LEFT JOIN cq l ON c.company = l.company AND c.mts > l.ts GROUP BY c.company, c.mts) AS c LEFT JOIN cq AS l ON l.company = c.company AND l.ts = c.mts LEFT JOIN cq AS l1 ON l1.company = c.company AND l1.ts = c.lts;

Puede observar los resultados en SQL Fiddle .

Esta consulta usa solo capacidades estándar de SQL y debería funcionar en cualquier RDBMS.