2017-06-21 4 views
0

La requête ci-dessous fonctionne mais est très coûteux en calcul (il y a> 14k enregistrements); cela peut-il être fait plus efficacement (par exemple sans une requête imbriquée)? Fondamentalement, il correspond à des instances dans la même table qui représentent une commande d'activation (log1) avec la commande d'arrêt de premier ordre (log2).Requête SQL: est-ce possible sans une requête imbriquée?

SELECT log1.`deviceID`, log1.`timestamp` AS `on`, log2.`timestamp` as `off` 
FROM `HC2_log_raw` log1, `HC2_log_raw` log2 
WHERE log1.`newValue` > 0 AND log1.`oldValue` = 0 AND log2.`newValue` = 0 AND log1.`deviceID` = log2.`deviceID` AND 
    log2.`timestamp` = 
    (SELECT MIN(log3.`timestamp`) 
    FROM `HC2_log_raw` log3 
    WHERE log3.`timestamp` > log1.`timestamp` AND log3.`deviceID` = log1.`deviceID` AND log3.`newValue`=0) 

Merci!

+0

documents 14k ne sont pas beaucoup. avez-vous déjà regardé le plan d'exécution? vous pourriez avoir juste besoin d'un index –

+0

avez-vous utilisé des index sur des colonnes conditionnées de jointure? –

+0

Cela n'aidera pas les performances, mais vous devriez passer à la syntaxe explicite 'join', c'est la norme ANSI depuis 1992! – HoneyBadger

Répondre

0

Vous pouvez essayer d'utiliser REJOIGNEZ avec GROUP BY et fonction MIN pour archiver vos résultats attendus

SELECT log1.`deviceid`, 
     log1.`timestamp`  AS `on`, 
     MIN(log2.`timestamp`) AS `off` 
FROM `hc2_log_raw` log1 
     INNER JOIN `hc2_log_raw` log2 
       ON log1.`deviceid` = log2.`deviceid` 
        AND log1.`timestamp` < log2.`timestamp` 
WHERE log1.`newvalue` > 0 
     AND log1.`oldvalue` = 0 
     AND log2.`newvalue` = 0 
GROUP BY log1.`deviceid`, log1.`timestamp` 
+0

Merci! Fonctionne comme un charme et environ 5 fois plus vite :) Merci pour tous les autres commentaires, j'ai encore besoin de créer des index appropriés, ce qui devrait le rendre encore plus rapide! – 3JL

+0

Un index sur deviceid et timestamp a seulement amélioré la vitesse de 20% btw – 3JL

+0

Avez-vous essayé de créer un index sur les champs newvalue et oldvalue? –

0

vérifiez cela. afaik, where clause fonctionne mieux que rejoindre on condition.

SELECT log1.`deviceID` 
    ,log1.`timestamp` AS `on` 
    ,log2.`timestamp` AS `off` 
FROM 
`HC2_log_raw` log1 
inner join `HC2_log_raw` log2 
on 
log1.`deviceID` = log2.`deviceID` 
where 
(
    log1.`newValue` > 0 
AND log1.`oldValue` = 0 
AND log2.`newValue` = 0 
AND log2.`timestamp` = (
     SELECT MIN(log3.`timestamp`) 
     FROM `HC2_log_raw` log3 
     WHERE log3.`timestamp` > log1.`timestamp` 
      AND log3.`deviceID` = log1.`deviceID` 
      AND log3.`newValue` = 0 
     ) 
)