Warum Select Top 100 Percent verwenden?

82

Ich verstehe, dass Sie vor SQL Server 2005 SQL Server "austricksen" konnten, um die Verwendung einer Reihenfolge in einer Ansichtsdefinition zu ermöglichen, indem Sie sie auch TOP 100 PERCENTin die SELECT- Klausel aufnehmen. Ich habe jedoch anderen Code gesehen, den ich geerbt habe und der SELECT TOP 100 PERCENT... in dynamischen SQL-Anweisungen verwendet (in ADO in ASP.NET- Apps usw. verwendet). Gibt es dafür einen Grund? Ist das Ergebnis nicht dasselbe wie das Nichteinbeziehen des TOP 100 PERCENT?

Ed Schembor
quelle
5
Vielleicht wird gerade eine Anweisung erstellt: "SELECT TOP {0} PERCENT ..."
Michael Petrotta
Ihr erster Satz ist die Antwort auf eine meiner versteckten Fragen geworden.
Muhammad Ashikuzzaman
Ich benutze die Top 99,9999999 Prozent und es funktioniert immer. Es ist nah genug. Ich neige dazu, die Anzahl der '9' basierend auf der erwarteten Anzahl der Datensätze anzuhängen. Mehr Rekorde, mehr Neuner und es funktioniert immer. Ich habe über SQL 2008 bis SQL 2017 verwendet.
Pedi

Antworten:

51

Es wurde für " Zwischenmaterialisierung (Google-Suche) " verwendet

Guter Artikel: Adam Machanic: Die Geheimnisse der Zwischenmaterialisierung erforschen

Er hat sogar ein MS Connect angehoben, damit es sauberer gemacht werden kann

Meine Ansicht ist "nicht von Natur aus schlecht", aber verwenden Sie sie nur, wenn Sie 100% sicher sind. Das Problem ist, dass es nur zu dem Zeitpunkt funktioniert, zu dem Sie es tun, und wahrscheinlich nicht später (Patch-Level, Schema, Index, Zeilenanzahl usw.) ...

Gearbeitetes Beispiel

Dies kann fehlschlagen, weil Sie nicht wissen, in welcher Reihenfolge die Dinge ausgewertet werden

SELECT foo From MyTable WHERE ISNUMERIC (foo) = 1 AND CAST(foo AS int) > 100

Und das kann auch daran scheitern

SELECT foo
FROM
    (SELECT foo From MyTable WHERE ISNUMERIC (foo) = 1) bar
WHERE
    CAST(foo AS int) > 100

Dies war jedoch in SQL Server 2000 nicht der Fall. Die innere Abfrage wird ausgewertet und gespoolt:

SELECT foo
FROM
    (SELECT TOP 100 PERCENT foo From MyTable WHERE ISNUMERIC (foo) = 1 ORDER BY foo) bar
WHERE
    CAST(foo AS int) > 100

Beachten Sie, dass dies in SQL Server 2005 weiterhin funktioniert

SELECT TOP 2000000000 ... ORDER BY...
gbn
quelle
Warum schlägt die zweite Abfrage fehl? Weil die innere Abfrage nicht (unbedingt) vollständig ausgewertet ist?
Kenny Evitt
Dieser zweite Link erklärt, warum das Erstellen von temporären Tabellen manchmal zu dramatischen Leistungsverbesserungen führt!
Kenny Evitt
40

TOP (100) PERCENT ist in neueren Versionen von SQL Server völlig bedeutungslos und wird (zusammen mit dem entsprechenden ORDER BY im Fall einer Ansichtsdefinition oder einer abgeleiteten Tabelle) vom Abfrageprozessor ignoriert.

Sie haben Recht, dass es einmal als Trick verwendet werden konnte, aber selbst dann war es nicht zuverlässig. Leider haben einige der grafischen Tools von Microsoft diese bedeutungslose Klausel eingefügt.

Ich habe keine Ahnung, warum dies in dynamischem SQL angezeigt wird. Sie haben Recht, dass es keinen Grund dafür gibt und das Ergebnis ohne es dasselbe ist (und im Fall einer Ansichtsdefinition oder einer abgeleiteten Tabelle auch ohne die Klauseln TOP und ORDER BY).

Steve Kass
quelle
Das ist nicht wahr; Siehe diesen Link aus der Antwort von @gbn für Details.
Kenny Evitt
3
Der Link, auf den Sie verweisen, sagt nichts über SELECT TOP (100) PERCENT .. ORDER BY aus, was bedeutungslos ist. Der Link erwähnt die Verwendung von SELECT TOP (2147483647). ORDER BY. Derzeit entfernt das SQL Server-Optimierungsprogramm SELECT TOP (100) PERCENT .. ORDER BY, da es bedeutungslos ist. Diese Kombination definiert immer dieselbe Zeilensammlung wie SELECT ohne TOP / ORDER BY. Das Optimierungsprogramm versucht derzeit nicht festzustellen, ob 2147483647 alle Zeilen umfasst, sodass in diesem Fall die Kombination TOP - ORDER BY nicht entfernt wird.
Steve Kass
2
In dem Link wird tatsächlich Folgendes erwähnt TOP (100) PERCENT: "... Ich könnte versuchen, eine Zwischenmaterialisierung der abgeleiteten Tabelle ohne temporäre Tabelle zu erzwingen, indem ich TOP 100 PERCENT in Verbindung mit ORDER BY verwende. Leider hat das SQL Server-Abfrageoptimierungsteam entschieden, dass dies nicht der Fall ist." Es ist eine gute Idee, und der Optimierer ignoriert solche Versuche jetzt. " Es unterstützt Sie in der Tat.
Kenny Evitt
Ich würde meine Ablehnung rückgängig machen, wenn ich könnte . [Wenn Sie Ihre Antwort bearbeiten, werde ich sie positiv bewerten.]
Kenny Evitt
1
Sie sind wahrscheinlich verwirrt, weil ich es mir anders überlegt habe. mein erster Kommentar war falsch; Du hast recht.
Kenny Evitt
23

... die Verwendung eines ORDER BY in einer Ansichtsdefinition zulassen.

Das ist keine gute Idee. In einer Ansicht sollte niemals ORDER BY definiert sein.

Ein ORDER BY wirkt sich auf die Leistung aus. Wenn Sie eine Ansicht verwenden, wird das ORDER BY im EXPLAIN-Plan angezeigt. Wenn Sie eine Abfrage haben, bei der die Ansicht mit etwas in der unmittelbaren Abfrage verknüpft ist oder auf die in einer Inline-Ansicht verwiesen wird (CTE / Unterabfrage-Factoring), wird ORDER BY immer vor dem endgültigen ORDER BY ausgeführt (vorausgesetzt, es wurde definiert). Das Bestellen von Zeilen, die nicht die endgültige Ergebnismenge sind, hat keinen Vorteil, wenn die Abfrage nicht TOP (oder LIMIT für MySQL / Postgres) verwendet.

Erwägen:

CREATE VIEW my_view AS
    SELECT i.item_id,
           i.item_description,
           it.item_type_description
      FROM ITEMS i
      JOIN ITEM_TYPES it ON it.item_type_id = i.item_type_id
  ORDER BY i.item_description

...

  SELECT t.item_id,
         t.item_description,
         t.item_type_description
    FROM my_view t
ORDER BY t.item_type_description

... entspricht der Verwendung von:

  SELECT t.item_id,
         t.item_description,
         t.item_type_description
    FROM (SELECT i.item_id,
                 i.item_description,
                 it.item_type_description
            FROM ITEMS i
            JOIN ITEM_TYPES it ON it.item_type_id = i.item_type_id
        ORDER BY i.item_description) t
ORDER BY t.item_type_description

Das ist schlecht, weil:

  1. In diesem Beispiel wird die Liste zunächst nach der Artikelbeschreibung sortiert und anschließend anhand der Artikeltypbeschreibung neu angeordnet. Bei der ersten Sortierung werden Ressourcen verschwendet - das Ausführen bedeutet nicht, dass es ausgeführt wird:ORDER BY item_type_description, item_description
  2. Es ist nicht offensichtlich, nach welcher Reihenfolge die Ansicht aufgrund der Kapselung geordnet ist. Dies bedeutet nicht, dass Sie mehrere Ansichten mit unterschiedlichen Sortierreihenfolgen erstellen sollten ...
OMG Ponys
quelle
6

Wenn es keine ORDER BYKlausel gibt, TOP 100 PERCENTist sie überflüssig. (Wie Sie bereits erwähnt haben, war dies der "Trick" mit Ansichten)

[Hoffentlich optimiert der Optimierer dies weg.]

Mitch Wheat
quelle
5

Ich habe anderen Code gesehen, den ich geerbt habe und der SELECT TOP 100 PERCENT verwendet

Der Grund dafür ist einfach: Enterprise Manager hat versucht, hilfreich zu sein und Ihren Code so zu formatieren, dass er dies für Sie enthält. Es hatte keinen Sinn, jemals zu versuchen, es zu entfernen, da es nichts wirklich verletzte und das nächste Mal, wenn Sie es änderten, EM es wieder einfügte.

Joel Coehoorn
quelle
4

Kein Grund außer Gleichgültigkeit, würde ich vermuten.

Solche Abfragezeichenfolgen werden normalerweise von einem grafischen Abfragetool generiert. Der Benutzer verbindet einige Tabellen, fügt einen Filter und eine Sortierreihenfolge hinzu und testet die Ergebnisse. Da der Benutzer die Abfrage möglicherweise als Ansicht speichern möchte, fügt das Tool TOP 100 PERCENT hinzu. In diesem Fall kopiert der Benutzer jedoch die SQL in seinen Code, parametrisiert die WHERE-Klausel und versteckt alles in einer Datenzugriffsschicht. Aus dem Kopf, aus den Augen.

Peter Radocchia
quelle
1

Bitte versuchen Sie das Folgende, hoffe, es wird für Sie funktionieren.

      SELECT TOP
              ( SELECT COUNT(foo) 
                  From MyTable 
                 WHERE ISNUMERIC (foo) = 1) * 
                  FROM bar WITH(NOLOCK) 
              ORDER BY foo
                 WHERE CAST(foo AS int) > 100
               )
Lakshminarayanan E.
quelle
1

Der Fehler sagt alles ...

Nachricht 1033, Ebene 15, Status 1, Prozedur TestView, Zeile 5 Die ORDER BY-Klausel ist in Ansichten, Inline-Funktionen, abgeleiteten Tabellen, Unterabfragen und allgemeinen Tabellenausdrücken ungültig, sofern nicht auch TOP, OFFSET oder FOR XML angegeben sind.

Verwenden Sie nicht TOP 100 PERCENT, verwenden Sie TOP n, wobei N eine Zahl ist

Der TOP 100 PERCENT (aus Gründen, die ich nicht kenne) wird von SQL Server VIEW (Versionen nach 2012) ignoriert, aber ich denke, MS hat ihn aus Syntaxgründen beibehalten. TOP n ist besser und funktioniert in einer Ansicht und sortiert sie wie gewünscht, wenn eine Ansicht anfänglich verwendet wird. Seien Sie jedoch vorsichtig .

Fandango68
quelle
0

Ich würde annehmen, dass Sie eine Variable im Ergebnis verwenden können, aber abgesehen davon, dass Sie das Stück ORDER BY in einer Ansicht erhalten, sehen Sie keinen Vorteil, wenn Sie implizit "TOP 100 PERCENT" angeben:

declare @t int
set @t=100
select top (@t) percent * from tableOf
Lauren Glenn
quelle
2
Die Frage ist Why use Select Top 100 Percentnicht, eine variable Anzahl für den Prozentsatz zu erhalten.
Bummi
0

Probieren Sie es einfach aus, es erklärt es so ziemlich selbst. Sie können keine Ansicht mit einem ORDER BY erstellen, außer wenn ...

CREATE VIEW v_Test
         AS
           SELECT name
             FROM sysobjects
         ORDER BY name
        GO

Nachricht 1033, Ebene 15, Status 1, Prozedur TestView, Zeile 5 Die ORDER BY-Klausel ist in Ansichten, Inline-Funktionen, abgeleiteten Tabellen, Unterabfragen und allgemeinen Tabellenausdrücken ungültig, sofern nicht auch TOP, OFFSET oder FOR XML angegeben sind.

John Brewster
quelle