web-dev-qa-db-fra.com

Pourquoi utiliser Select Top 100 Percent?

Je comprends qu'avant SQL Server 2005, vous pouviez "tromper" SQL Server pour permettre l'utilisation d'un ordre dans une définition de vue, en incluant également TOP 100 PERCENT dans la clause SELECT. Mais j’ai vu un autre code dont j’ai hérité qui utilise SELECT TOP 100 PERCENT ... dans des instructions SQL dynamiques (utilisé dans ADO dans ASP.NET apps, etc.). Y a-t-il une raison quelconque pour cela? Le résultat n'est-il pas identique à not incluant le TOP 100 PERCENT?

76
Ed Schembor

Il a été utilisé pour " matérialisation intermédiaire (recherche Google) "

Bon article: Adam Machanic: Exploration des secrets de la matérialisation intermédiaire

Il a même soulevé un MS Connect afin que cela puisse se faire de manière plus propre

Mon point de vue n'est "pas fondamentalement mauvais", mais ne l'utilisez pas à moins de 100%. Le problème est que cela ne fonctionne que lorsque vous le faites et probablement pas plus tard (niveau de patch, schéma, index, nombre de lignes, etc.).

Exemple travaillé

Cela peut échouer car vous ne savez pas dans quel ordre les objets sont évalués

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

Et cela peut aussi échouer parce que

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

Toutefois, cela n'a pas été le cas dans SQL Server 2000. La requête interne est évaluée et mise en file d'attente:

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

Notez que cela fonctionne toujours dans SQL Server 2005

SELECT TOP 2000000000 ... ORDER BY...
50
gbn

TOP (100) PERCENT n'a aucune signification dans les versions récentes de SQL Server et est ignoré par le processeur de requête (avec ORDER BY correspondant, dans le cas d'une définition de vue ou d'une table dérivée).

Vous avez raison, il était une fois, cela pouvait être utilisé comme une astuce, mais même alors, ce n'était pas fiable. Malheureusement, certains des outils graphiques de Microsoft ont mis cette clause dénuée de sens.

Quant à savoir pourquoi cela pourrait apparaître en SQL dynamique, je n'en ai aucune idée. Vous avez raison de dire qu'il n'y a pas de raison, et le résultat est le même sans elle (et encore, dans le cas d'une définition de vue ou d'une table dérivée, sans les clauses TOP et ORDER BY).

38
Steve Kass

... autorise l'utilisation de ORDER BY dans une définition de vue.

Ce n'est pas une bonne idée. Une vue ne doit jamais avoir un ORDER BY défini.

Un ORDER BY a un impact sur les performances - son utilisation dans une vue signifie que ORDER BY apparaîtra dans le plan Expliquer. Si vous avez une requête dans laquelle la vue est jointe à quoi que ce soit dans la requête immédiate ou référencée dans une vue en ligne (CTE/factorisation de sous-requête), ORDER BY est toujours exécuté avant le dernier ORDER BY (en supposant qu'il ait été défini). Il n'y a aucun avantage à commander des lignes qui ne sont pas le résultat final lorsque la requête n'utilise pas TOP (ou LIMIT pour MySQL/Postgres). 

Considérer:

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

... équivaut à utiliser:

  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

C'est mauvais parce que:

  1. L'exemple consiste à classer la liste initialement en fonction de la description de l'article, puis à la réorganiser en fonction de la description du type d'élément. Le premier tri consiste en un gaspillage de ressources. Si vous utilisez not, cela signifie: ORDER BY item_type_description, item_description
  2. Il n’est pas évident de définir la vue en raison de l’encapsulation. Cela ne signifie pas que vous devez créer plusieurs vues avec différents ordres de tri ...
22
OMG Ponies

S'il n'y a pas de clause ORDER BY, alors TOP 100 PERCENT est redondant. (Comme vous le mentionnez, c'était le "truc" avec des vues)

[Espérons que l'optimiseur optimisera cela.]

5
Mitch Wheat

Aucune raison mais indifférence, je suppose.

De telles chaînes de requête sont généralement générées par un outil de requête graphique. L'utilisateur joint quelques tables, ajoute un filtre, un ordre de tri et teste les résultats. Étant donné que l'utilisateur peut vouloir enregistrer la requête sous forme de vue, l'outil ajoute un TOP 100 POUR CENT. Dans ce cas, cependant, l'utilisateur copie le code SQL dans son code, paramètre la clause WHERE et masque tout dans une couche d'accès aux données. Loin des yeux, loin des yeux.

4
Peter Radocchia

J'ai vu un autre code dont j'ai hérité qui utilise SELECT TOP 100 PERCENT

La raison en est simple: Enterprise Manager essayait d’être utile et formaterait votre code pour l’inclure à votre place. Il était inutile d'essayer de l'enlever car cela ne faisait vraiment pas mal et la prochaine fois que vous alliez le changer, EM l'insérerait à nouveau. 

4
Joel Coehoorn

Veuillez essayer ci-dessous, j'espère que cela fonctionnera pour vous.

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

L'erreur dit tout ...

Msg 1033, Niveau 15, Etat 1, Procédure TestView, Ligne 5 La clause ORDER BY n'est pas valide dans les vues, les fonctions en ligne, les tables dérivées, les sous-requêtes et les expressions de table communes, sauf si TOP, OFFSET ou FOR XML est également spécifié.

N'utilisez pas TOP 100 PERCENT, utilisez TOP n, où N est un nombre

Le TOP 100 POUR CENT (pour des raisons que je ne connais pas) est ignoré par SQL Server VIEW (versions post-2012), mais je pense que MS l'a conservé pour des raisons de syntaxe. TOP n est préférable. Elle fonctionne dans une vue et la trie comme vous le souhaitez lorsqu’une vue est utilisée au départ, mais soyez prudent .

0
Fandango68

Essayez ceci, cela s’explique presque tout seul. Vous ne pouvez pas créer une vue avec ORDER BY sauf si ...

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

Msg 1033, Niveau 15, Etat 1, Procédure TestView, Ligne 5 La commande ORDER BY La clause n'est pas valide dans les vues, les fonctions en ligne, les tables dérivées, sous-requêtes et expressions de table communes, sauf TOP, OFFSET ou FOR XML est également spécifié.

0
John Brewster

Je suppose que vous pouvez utiliser une variable dans le résultat, mais mis à part obtenir la pièce ORDER BY dans une vue, vous ne verrez aucun avantage en indiquant implicitement "TOP 100 POUR CENT":

declare @t int
set @t=100
select top (@t) percent * from tableOf
0
Lauren Glenn