2012-12-10 1 views
6

ich habe eine Abfrage wie folgt auszuführen:Wie kann ich zwingen SQL Server subquery erste und filtern das ‚wo‘ Anweisung

select * from (
    select * from TableX 
    where col1 % 2 = 0 
) subquery 
where col1 % 4 = 0 

Die tatsächliche Unterabfrage ist komplizierter. wenn ich die Unterabfrage allein ausführe, gibt es vielleicht 200 Zeilen schnell zurück, aber wenn ich die ganze Abfrage ausführe, dauert es zu lange, bis ich darauf warten muss.

Ich weiß SQL-Server nimmt einige Optimierung hier und fügen Sie die where-Anweisung in die Unterabfrage, und erstellen Sie den neuen Ausführungsplan, der nicht so effizient ist. Trotzdem kann ich in den Ausführungsplan eintauchen und analysieren, warum, wie der Index fehlt, die Statistik veraltet ist.

Aber ich weiß sicher, dass meine Unterabfrage, die als BaseTable dient, nur einen kleinen Teil der Daten zurückgibt, so dass ich alle weiteren Filterung oder Verbindung nur in diesen kleinen Teil der Daten stattfinden soll.

Meine Frage ist, kann ich SQL Server zwingen, die Unterabfrage zuerst auszuführen, ohne sich um die äußere where Aussage zu kümmern? (Btw, TempTable ist meine letzte Option, CTE funktioniert nicht)

+0

Was ist mit einer temporären Tabelle? – fnurglewitz

+1

Was ist mit Ihnen zu erklären, das eigentliche Problem - nicht erzwingen, aber überprüfen Sie den Ausführungsplan und schauen Sie, warum SQL Server denkt, dass es so klüger ist. Bist du vollständig gepatcht? Einige Probleme waren im Apst mit Abfrageoptimierer - lange in der Vergangenheit, aber einige Leute verwenden immer noch SQL Server 2005. – TomTom

+1

@TomTom Diese Prädikate sind nicht darstellbar, so dass es sehr wahrscheinlich ist, dass die Optimiererschätzungen aus sind. Es kann keine Statistiken verwenden und muss nur raten. Vielleicht hilft das Erstellen von Statistiken für eine berechnete Spalte. –

Antwort

-2

Sie CTE dafür verwenden können:

with cte as(
select * from TableX where col1 % 2 = 0 
) 

select * from (select * from cte) subquery where col1 % 4 = 0 
+3

Das erzwingt keine bestimmte Reihenfolge der Auswertung. SQL Server führt die beiden Abfragen nur zusammen mit der abgeleiteten Tabelle im OP zusammen. –

+0

cte nicht zwingen, Abfragen in beliebiger Reihenfolge auszuführen. – danihp

+0

@MartinSmith: Wie pro Frage will es die innere Abfrage zuerst ausführen, ohne sich um die äußere 'where' Anweisung zu kümmern –

-1

enter image description here

CREATE TABLE [dbo].[Performance](
    [Id1] [int] NOT NULL, 
    [Id2] [int] NOT NULL, 
    [Id3] [int] NOT NULL, 
    [Description] [varchar](50) NOT NULL, 
CONSTRAINT [PK_Performance] PRIMARY KEY CLUSTERED 
(
    [Id1] ASC, 
    [Id2] ASC, 
    [Id3] ASC 
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) 
) 

select count(*) from [Performance] = 2.000.000

select 
    a.* 
from 
    [Performance] a 
    inner join (
     select Id1,Id2,Id3,Description from [Performance] where (id1 % 2 = 0) 
    ) b on (a.id1 = b.id1) 
where 
    (b.Id3 % 3 = 0) 

Self-Join mit abgeleiteten Tabelle

Die Ergebnisse sind ziemlich schnell, würde ich sagen (200.000 Zeilen).

enter image description here

-1

Haben Sie versucht:

select * from ( select * from TableX as inner where inner.col1 % 2 = 0 ) as subquery where subquery.col1 % 4 = 0

Ich glaube, es zuerst hier die Unterabfrage ausführen muss, weil Sie auf dem aliased Ergebnis der Unterabfrage, die in den Zustand explizit haben.