2016-07-08 12 views
0

Könnte mir bitte jemand helfen, diese Abfrage zu optimieren/neu zu schreiben? Ich denke, ich habe ein paar Dos und Dont's in diesem einen verletzt.SQL-Abfrageoptimierung mit Unterabfragen

SELECT 
    p.PropertyTagNumber, 
    Last_Inv_Hist.Plant, 
    Last_Inv_Hist.Location, 
    (
     SELECT  TOP (1) comment_txt 
     FROM   Comment 
     WHERE  (property_id = p.ID) 
     ORDER BY id DESC 
    ) AS Remarks 

FROM Property AS p 
LEFT OUTER JOIN 
(
    SELECT  i.ID, i.PropertyID, i.Location, pl.Plant 
    FROM InventoryHistory AS i LEFT OUTER JOIN 
    Plants AS pl ON i.PlantID = pl.ID 
    WHERE (i.ID = ( SELECT  TOP (1) ID AS max_id 
       FROM   InventoryHistory 
       WHERE  (PropertyID = i.PropertyID) 
       ORDER BY InventoryDate DESC 
      ) 
     ) 
) AS Last_Inv_Hist 
    ON p.ID = Last_Inv_Hist.PropertyID 
+3

Markieren Sie Ihre Frage mit der Datenbank, die Sie verwenden. –

+3

Leistungsfragen sollten "EXPLAIN ANALYSE" und einige Informationen über Tabellengröße, Index, aktuelle Zeitleistung, Wunschzeit usw. enthalten. "Langsam" ist ein relativer Begriff, und wir brauchen einen echten Vergleichswert. –

+1

das wahrscheinlich gehört auf [codereview.se] –

Antwort

0

Hier ist, wie ich es tun würde,

WITH inv AS 
(
    SELECT ID, PropertyID, Location, pl.Plant, 
      ROW_NUMBER() OVER (PARTITION BY ID ORDER BY InventoryDate DESC) as DateOrder 
    FROM InventoryHistory 
), MaxInv AS 
(SELECT ID, PropertyID, Location, Plant 
    FROM inv 
    WHERE DateOrder = 1 
), MaxComment AS 
(
    SELECT comment_txt, property_id 
    FROM (
    SELECT comment_txt, property_id, 
      ROW_NUMBER() OVER (PARTITION BY property_id ORDER BY ID DESC) AS IdOrder 
    FROM Comment 
) X 
    WHERE IdOrder = 1 
) 
SELECT 
    p.PropertyTagNumber, 
    MaxInv.Plant, 
    MaxInv.Location, 
    MaxComment.Comment_txt 
FROM Property AS p 
LEFT JOIN MaxComment On p.ID = MaxComment.propertyID 
LEFT JOIN MaxInv ON ON p.ID = MaxInv.PropertyID 

einige Noten -

  • Indem Sie den Code, den Max-Wert für eine bestimmte Spalte in einem WAK findet (oder Sie könnten eine Unterabfrage verwenden, ich denke nur, dass CTE leichter zu lesen ist. Sie tun nur eine Auswahl - in Ihrem Code machen Sie eine Auswahl für jede Zeile (außer Ihr Produkt ist schlau genug um zu optimieren.)

  • Ich zeige Ihnen zwei Möglichkeiten, den CTE absichtlich zu machen - manche mögen einen Weg über den anderen.

  • Ich finde die Kommentarwahl sehr seltsam - warum ID verwenden, um zu entscheiden, welches zu zeigen?

+0

Danke für die mich auf die Composite-Tabelle. Jetzt gerade lernen, dass es Temp-Tabelle ähnlich ist. Ich dachte über die Verwendung der temporären Tabelle, um einige der Unterabfragen zu speichern, war mir aber nicht sicher, ob es mir etwas kauft. – Steve

+0

Diese werden CTEs - Common Table Expressions genannt. Common bedeutet in diesem Fall geteilt. Sie sollten wahrscheinlich CTEs anstelle von temporären Tabellen verwenden, wenn Sie können, im Allgemeinen wird die Leistung besser sein, weil der Compiler/Server optimieren kann, wie sie basierend auf einer Anzahl von Faktoren gespeichert werden. – Hogan