2010-10-30 7 views
3

J'ai une table dans laquelle je garde différents compteurs (compteur d'eau, compteur d'électricité) et dans un autre tableau je garde les lectures pour chaque compteur. La structure de la table est comme ceci: Le tableau mètresSELECT pour obtenir deux entrées, du même tableau, différenciées par date, dans une rangée

MeterID | MeterType | MeterName 

Les lectures de la table:

ReadingID | MeterID | Index | DateOfReading 

Les lectures d'un compteur sont lus chaque mois. La chose que j'essaye de faire maintenant est d'obtenir l'information de mètre, la lecture courante et la lecture précédente dans juste une rangée. Donc, si j'aurais une requête, la ligne suivante entraînerait:

MeterID | MeterType | MeterName | CurrnetIndex | LastIndex 

J'ai la requête suivante jusqu'à présent:

SELECT Meter.MeterID, Meter.MeterType, Meter.MeterName, CurrentReading.Index, PreviousReading.Index 
FROM Meters AS Meter 
LEFT OUTER JOIN Readings AS CurrentReading ON Meter.MeterID = CurrentReading.MeterID 
LEFT OUTER JOIN Readings AS PreviousReading ON Meter.MeterID = PreviouseReading.MeterID 
WHERE CurrentReading.ReadingID != PreviousReading.ReadingID AND DIMESTAMPDIFF(MONTH, CurrentReading.DateOfReading, PreviousReding.DateOfReading)=-1 

Le problème est que je ne peux pas avoir la lecture en cours ou précédent , ou les deux, mais je voudrais encore avoir récupéré les informations du compteur. Il est parfaitement acceptable pour moi d'obtenir des colonnes NULL, mais j'ai encore besoin d'une rangée :)

Répondre

2

Utilisation:

SELECT m.meterid, 
      m.metertype, 
      m.metername, 
      current.index, 
      previous.index 
    FROM METER m 
LEFT JOIN READING current ON current.meterid = m.meterid 
         AND MONTH(current.dateofreading) = MONTH(NOW()) 
LEFT JOIN READING previous ON previous.meterid = m.meterid 
          AND MONTH(current.dateofreading) = MONTH(NOW())-1 

Être un OUTER JOIN - si la filtration du mois est fait dans la clause WHERE, il peut produire des résultats différents que étant fait dans la clause ON.

+0

+1 pour l'utilisation de plusieurs conditions sur 'LEFT JOIN' –

0

Eh bien, la philosophie SQL est de stocker ce que vous savez. Si vous ne le savez pas, il n'y a pas de ligne pour cela. Si vous faites un filtre sur le jeu d'enregistrements que vous recherchez, et ne trouvez rien, alors il n'y a pas de mois pour le lire. Ou que je ne comprenais pas la question

1

Vous pouvez utiliser une sous-requête pour saisir la valeur il y a un mois:

select * 
,  (
     select Index 
     from Readings r2 
     where r2.MeterID = m.MeterID 
       and DIMESTAMPDIFF(MONTH, r1.DateOfReading, 
            r2.DateOfReading) = -1 
     ) as LastIndex 
from Meter m 
left join 
     Readings r1 
on  r1.MeterID = m.MeterID 

Une autre solution est de permettre à la deuxième jointure gauche à l'échec. Vous pouvez le faire en changeant simplement votre clause where:

WHERE PreviousReading.ReadingID is null 
     or 
     (
      CurrentReading.ReadingID != PreviousReading.ReadingID 
      and 
      DIMESTAMPDIFF(MONTH, CurrentReading.DateOfReading, 
         PreviousReding.DateOfReading) = -1 
     ) 
+0

Vous répondez mieux, j'ai voté et supprimé le mien. – Knubo

Questions connexes