2016-04-01 1 views
1

Ich habe eine Ansicht, die LAG verwendet.Fensterfunktionen in der Ansicht, die mit "wo" aufgerufen wird, gibt einen fehlerhaften Ausführungsplan aus

Wenn ich es mit "WHERE" aufrufen, bekommt es einen Ausführungsplan viel schlechter als wenn nur die Abfrage aufgerufen wird.

SELECT 
    ID, 
    PlacementID, 
    LAG(Reading, 1) OVER (PARTITION BY MeterNumber ORDER BY Date) AS Val 
FROM dbo.ImportedReadingDay 
WHERE (PlacementID = 12404) 

SELECT * 
FROM V_ImportedReadingDay2 
WHERE (PlacementID = 12404) 

enter image description here

Dies ist ein bekanntes Problem. Sie können das Problem googlen. Ich habe zwei Lösungen gefunden. Verwenden Sie entweder eine Tabellenwertfunktion oder verschieben Sie die LAG außerhalb der Ansicht.

ABER ich würde gerne wissen, ob es andere Lösungen gibt, da keine von diesen für mich arbeiten, da ich die Ansicht in einer Client-Software verwenden muss.

Antwort

3

Ihre zwei Abfragen sind logisch nicht identisch. Natürlich erhalten sie nicht den gleichen Ausführungsplan.

diese Abfragen Bedenken Sie:

select name,LAG(column_id) OVER (ORDER BY system_type_id) as cid 
from sys.columns 
where name='name' 

select * from (
select name,LAG(column_id) OVER (ORDER BY system_type_id) as cid 
from sys.columns 
) t 
where name='name' 

Aufgrund der logischen Verarbeitungsreihenfolge von Abfragen, die WHERE Klausel vor der SELECT Klausel verarbeitet. Also, für die erste Abfrage, wir zuerst Filter die sys.columns Tabelle, nur Zeilen mit einem bestimmten Namen, und dann dann wenden wir die LAG() Funktion nur auf diese gefilterte Menge (so wird der verzögerte Wert definitiv aus einer anderen Zeile kommen was zum Filter passt).

Für die zweite Abfrage verarbeiten wir zuerst (logisch) die Unterabfrage. Wir führen die LAG()-Funktion über den gesamten Satz von Zeilen aus (weil die Unterabfrage keine Filter enthält/WHERE -Klausel) und dann (in der äußeren Abfrage) filtern wir den Satz von Zeilen. Das bedeutet, dass der verzögerte Wert möglicherweise aus einer Zeile gezogen wurde, die nicht mit dem endgültigen Filter übereinstimmt.

Nun, wenn Sie eine Ansicht verwenden, ist es ähnlich wie bei meiner zweiten Abfrage. Der Wert von Val, der abgerufen wird, wenn Sie Ihre Ansicht verwenden, ist nicht garantiert aus einer Zeile mit einer PlacementID gleich 12404 sein.

+0

Ich weiß, wie ich schon sagte, sie sind vereinfacht. – Kvasi

+0

Die gleiche Analyse gilt immer noch - in der direkten Abfrage gegen die Tabelle Groß- und Kleinschreibung, logisch * filter * und * dann * 'LAG', und in der Ansichtsabfrage sind Sie' LAG', bevor Sie filtern. Sie sind logisch noch verschiedene Abfragen. –

+0

Nun ja, die LAG sollte in der Lage sein, aus einer Zeile zu holen, die nicht zum selben Filter passt, da der Wert zu einem Meter gehört, der von einem Platz zu einem anderen verschoben werden könnte, ohne den Lesewert zurückzusetzen. Obwohl ich erkannte, dass selbst wenn ein LAG-Wert korrekt zu einem früheren Placement gehören konnte, war es nicht sinnvoll. Also ja, du hast Recht, dass sie nicht gleich sind. – Kvasi

1

Dies war eine vereinfachte Ansicht nur für dieses Beispiel. Im echten partitioniere ich die LAG. Ich fand heraus, dass die Partitionierung der LAG mit der gleichen wie in der "WHERE" (in diesem Fall PlacementID) das Leistungsproblem gelöst.

Verwandte Themen