2012-07-03 2 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 | 

Comment puis-je faire un décalage sur cette table MySQL pour imprimer la différence entre guillemets, par exemple:Simuler fonction de retard dans MySQL

GOOGLE | 20 
SAP | 40 
+0

Y a-t-il seulement deux par société? ou est-ce variable? –

+0

ce sont deux entreprises – javanx

+0

Je vois que vous avez deux entreprises ici, mais y a-t-il seulement deux lignes par entreprise? Si c'est le cas, vous pouvez utiliser trivialement les agrégats 'MAX() - MIN()'. S'il y a plus de 2 lignes par 'company', c'est plus compliqué. –

Répondre

33

Ceci est mon préféré MySQL hack.

Voici comment vous imitez la fonction lag:

SET @quot=-1; 
select time,company,@quot lag_quote, @quot:=quote curr_quote 
    from stocks order by company,time; 
  • lag_quote détient la valeur de la citation de la ligne précédente. Pour la première ligne @quot est -1.
  • curr_quote contient la valeur de l'offre de la ligne en cours.

Notes:

  1. order by clause est important ici, tout comme il est dans une fonction régulière de la fenêtre.
  2. Vous pouvez également utiliser lag pour company juste pour être sûr que vous calculez la différence entre guillemets de la même company.
  3. Vous pouvez également mettre en place des compteurs de ligne de la même manière @cnt:[email protected]+1

La bonne chose à propos de ce régime est qu'il est informatiquement très maigre par rapport à d'autres approches comme l'utilisation des fonctions d'agrégation, des procédures stockées ou des données de traitement dans le serveur d'applications .

EDIT:

Venons-en maintenant à votre question d'obtenir résultat dans le format que vous avez mentionné:

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; 

L'imbrication est pas co-lié donc pas aussi mauvais (informatiquement) comme il semble (syntaxiquement) :)

Faites-moi savoir si vous avez besoin d'aide avec ceci.

+0

Je reçois une erreur. Les instructions DDL et DML ne sont pas autorisées dans le panneau de requête pour MySQL; Seules les instructions SELECT sont autorisées. Placez DDL et DML dans le panneau de schéma. – javanx

+0

Bien que l'erreur ne l'indique pas, essayez d'activer "allowMultiQueries". Ceci est un paramètre de connecteur. Pour le connecteur JDBC, voir: http://dev.mysql.com/doc/refman/5.1/en/connector-j-reference-configuration-properties.html. Êtes-vous capable de l'exécuter avec succès à partir du client MySQL? – Dojo

+0

Vous pouvez également essayer d'exécuter les deux instructions individuellement, mais dans la même session. – Dojo

2

Pour obtenir le résultat souhaité, vous devez d'abord rechercher le dernier et l'avant-dernier horodatage pour chaque société. Il est tout à fait simple avec la requête suivante:

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; 

Maintenant, vous devez joindre cette sous-requête avec la table d'origine pour obtenir les résultats souhaités:

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; 

Vous pouvez observer les résultats sur SQL Fiddle.

Cette requête utilise uniquement des fonctionnalités SQL standard et devrait fonctionner sur n'importe quel SGBDR.