2009-03-04 12 views
1

Ich habe gerade versucht, eine korrelierte Unterabfrage in der FROM-Klausel einer SELECT-Anweisung in Oracle zu tun, aber mir wurde ein Fehler angezeigt, dass ich die Korrelation (etwas, dass Obs.pID wurde nicht erkannt).Oracle korrelierte Unterabfrage in FROM-Liste

Sollte das funktionieren?

FROM ml.Person Person 
    JOIN ml.Obs ON Person.pID = Obs.pId 
     JOIN (SELECT ObsMax2.pId, ObsMax2.hdId 
       , MAX(ObsMax2.obsDate) as maxDate 
       FROM ml.Obs ObsMax2 
       WHERE ObsMax2.pId = Obs.pId 
        AND ObsMax2.obsDate < {?EndDate} 
       GROUP BY ObsMax2.pId, ObsMax2.hdId) ObsMax 
      ON Obs.pId = ObsMax.pId 
       AND Obs.hdId = ObsMax.hdId 
       AND Obs.obsDate = ObsMax.maxDate 

Meine Abhilfe scheint zu sein, es ist ein nicht-korrelierten Unterabfrage zu machen, und fügen Sie Kriterien für die Unterabfrage, die völlig Amok hält, Amok sie vom Laufen, amu-- oof Es tut uns leid.

Ich würde lieber herausfinden, wie man es richtig korreliert, obwohl, wenn möglich - die Ansicht, die wie diese Unterabfrage funktioniert, dauert ewig zu bauen.

+0

Sie wahrscheinlich die Abfrage Refactoring wollen, nicht nur diese syntaktische Problem beheben Sie laufen in zu. Erwägen Sie, die Frage zu klären, was Sie erreichen möchten. – Alkini

+1

@David - "Pedant" :-) @Alan - Ich bin nur nicht sicher, in welchem ​​Umfang ich über die Interna dieses Systems sprechen soll. Normalerweise würde ich eine integrierte Ansicht verwenden, die die Gruppierung nach pID/hdID durchführt, um die neueste Beobachtung zu erhalten - aber das scheitert, wenn es in 2009 ist und Sie 2008 abfragen. – SarekOfVulcan

Antwort

4

Sie können die Absicht dieses Teils der Abfrage erreichen, indem Sie eine analytische Funktion verwenden, um das maximale obsDate für jede PID und Hdid zu identifizieren.

Es wäre so etwas wie:

select ... 
from (
     SELECT pId, 
       hdId, 
       obsDate 
       MAX(obsDate) over (partition by pId, hdId) maxDate 
     FROM ml.Obs 
     WHERE obsDate < {?EndDate} 
     ) 
where obsDate = maxDate 
/
+0

Der Erklärungs-Plan für diese Version war ein bisschen besser als der, den ich mir ausgedacht habe, und es fühlt sich auch schneller an. Ich hatte diese nicht schon mal gesehen - Danke! – SarekOfVulcan

+0

keine probleme. Analytische Funktionen sind sehr cool. –

+1

Sie haben mir gerade gezeigt, wie man PARTITION BY benutzt, und mein Problem gelöst. –

3

Unterabfragen innerhalb einer FROM-Klausel können sich nicht auf andere Tabellen aus derselben FROM-Klausel beziehen. Das Entfernen der ObsMax2.pId = Obs.pId-Klausel sollte das Problem lösen, und von I kann sagen gibt Ihnen genau das gleiche Ergebnis, da die gleiche Klausel in der Join-Bedingung ist. Wie Sie jedoch bereits erwähnt haben, können Leistungsprobleme auftreten, wenn GROUP BY in der Unterabfrage enthalten ist.

Von was ich sagen kann, Sie versuchen, die einzelnen pID/hdId Datensätze von ml.Obs mit der größten ObsDate, die weniger als {EndDate} ist. In diesem Fall, was ist mit dem Verschieben der Unterabfrage in die WHERE-Klausel, wo Sie es korrelieren können? Zum Beispiel:

+0

Wenn dies der Fall ist, und insbesondere wenn Das Feld ist nur vom Typ Datum. Achten Sie darauf, dass mehr als eine Person zurückgegeben wird (aufgrund von doppelten Daten). – Alkini

+0

Ja, wenn die Kombination (pId, hdId, obsDate) nicht eindeutig ist, könnten Sie mehrere Datensätze pro (pId, hdId) Paar erhalten. Ich glaube, dass die ursprüngliche Abfrage das gleiche Problem haben würde. –

+0

Dies ist eine Abfrage für ein EMR (medizinische Aufzeichnungen) System. pId ist PersonId, hdId identifiziert eine medizinische Beobachtung (BP, Pulse, LDL, etc.) Daher müssten Sie sich keine Gedanken über das Duplizieren von pid/hdid/date machen - Sie haben einen Wert pro Dokument. – SarekOfVulcan

0

Sie haben viele Ihrer Tabellen mit "ml" vorangestellt. aber nicht überall (der erste Join zum Beispiel). Angenommen, Sie müssen, dass (für Benutzer/Berechtigungen/was auch immer).

JOIN ml.Obs ON Person.pID = ** ml ** Obs.pId

oder

ml.Obs JOIN Obs ON Person.pID = Obs.pId

Es gibt andere Orte, an denen dies auch benötigt würde.

Wenn dies nicht der Fall ist, entfernen Sie sie aus Ihrer Abfrage, weil sie irrelevant und störend sind.

Verwandte Themen