2012-07-03 11 views
23
| 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 hacer un retraso en esta tabla en MySQL para imprimir la diferencia entre comillas, por ejemplo:función de retardo Simular en MySQL

GOOGLE | 20 
SAP | 40 
+0

¿Hay solo dos por 'compañía'? o es variable? –

+0

estas son dos compañías – javanx

+0

Veo que tiene dos compañías aquí, ¿pero hay solo dos filas por compañía? Si es así, puede usar los agregados 'MAX() - MIN()' trivialmente. Si hay más de 2 filas por 'compañía', es más complicado. –

Respuesta

33

Ésta es mi favorito MySQL hackear.

Esta es la forma de emular la función de retardo:

SET @quot=-1; 
select time,company,@quot lag_quote, @quot:=quote curr_quote 
    from stocks order by company,time; 
  • lag_quote mantiene el valor de cotización 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 en este caso al igual que lo es en una función regular ventana.
  2. Es posible que también desee utilizar lag para company solo para asegurarse de que está calculando la diferencia en las comillas de la misma company.
  3. También puede implementar contadores de fila de la misma manera @cnt:[email protected]+1

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

EDIT:

Ahora que se acerca a su pregunta de conseguir resultado en el formato que usted ha mencionado:

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,[email protected] as change, @quot:=quote curr_quote 
from stocks order by company,time) A 
order by company,time desc) B where B.LATEST=1; 

El anidamiento no está co relacionado con lo que no es tan malo (computacionalmente) como se ve (sintácticamente) :)

Avíseme si necesita ayuda con esto.

+0

Recibo un error. Las sentencias DDL y DML no están permitidas en el panel de consulta para MySQL; solo se permiten las declaraciones SELECT. Coloque DDL y DML en el panel de esquema. – javanx

+0

Aunque el error no lo indica, intente habilitar "allowMultiQueries". Este es un parámetro de conector. Para el conector JDBC, consulte: http://dev.mysql.com/doc/refman/5.1/en/connector-j-reference-configuration-properties.html. ¿Eres capaz de ejecutarlo con éxito desde el cliente MySQL? – Dojo

+0

También puede intentar ejecutar las dos instrucciones individualmente pero en la misma sesión. – Dojo

2

Para lograr el resultado deseado, primero debe encontrar la última y la última marca de tiempo para cada compañía. Es bastante sencillo, 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 tiene que unirse a este sub consulta 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; 

Se pueden observar resultados en SQL Fiddle.

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