Sqlserver
 sql >> Base de données >  >> RDS >> Sqlserver

Créer une vue avec la clause ORDER BY

Je ne sais pas ce que vous pensez de ce ORDER BY s'accomplit ? Même si vous faites mettre ORDER BY dans la vue de manière légale (par exemple en ajoutant un TOP clause), si vous sélectionnez simplement dans la vue, par ex. SELECT * FROM dbo.TopUsersTest; sans ORDER BY clause, SQL Server est libre de renvoyer les lignes de la manière la plus efficace, qui ne correspondra pas nécessairement à l'ordre que vous attendez. C'est parce que ORDER BY est surchargé, en ce sens qu'il essaie de servir deux objectifs :trier les résultats et dicter les lignes à inclure dans TOP . Dans ce cas, TOP gagne toujours (bien qu'en fonction de l'index choisi pour analyser les données, vous pourriez observer que votre commande fonctionne comme prévu - mais ce n'est qu'une coïncidence).

Afin d'accomplir ce que vous voulez, vous devez ajouter votre ORDER BY clause aux requêtes qui extraient les données de la vue, et non au code de la vue elle-même.

Donc, votre code de vue devrait être :

CREATE VIEW [dbo].[TopUsersTest] 
AS 
  SELECT 
    u.[DisplayName], SUM(a.AnswerMark) AS Marks
  FROM
    dbo.Users_Questions AS uq
    INNER JOIN [dbo].[Users] AS u
      ON u.[UserID] = us.[UserID] 
    INNER JOIN [dbo].[Answers] AS a
      ON a.[AnswerID] = uq.[AnswerID]
    GROUP BY u.[DisplayName];

Le ORDER BY n'a pas de sens donc ne devrait même pas être inclus.

Pour illustrer, en utilisant AdventureWorks2012, voici un exemple :

CREATE VIEW dbo.SillyView
AS
  SELECT TOP 100 PERCENT 
    SalesOrderID, OrderDate, CustomerID , AccountNumber, TotalDue
  FROM Sales.SalesOrderHeader
  ORDER BY CustomerID;
GO

SELECT SalesOrderID, OrderDate, CustomerID, AccountNumber, TotalDue
FROM dbo.SillyView;

Résultats :

SalesOrderID   OrderDate   CustomerID   AccountNumber   TotalDue
------------   ----------  ----------   --------------  ----------
43659          2005-07-01  29825        10-4020-000676  23153.2339
43660          2005-07-01  29672        10-4020-000117  1457.3288
43661          2005-07-01  29734        10-4020-000442  36865.8012
43662          2005-07-01  29994        10-4020-000227  32474.9324
43663          2005-07-01  29565        10-4020-000510  472.3108

Et vous pouvez voir sur le plan d'exécution que le TOP et ORDER BY ont été absolument ignorés et optimisés par SQL Server :

Il n'y a pas de TOP opérateur du tout, et pas de tri. SQL Server les a complètement optimisés.

Maintenant, si vous changez la vue pour dire ORDER BY SalesID , vous obtiendrez alors l'ordre indiqué par la vue, mais seulement - comme mentionné précédemment - par coïncidence.

Mais si vous modifiez votre requête externe pour effectuer le ORDER BY vous vouliez :

SELECT SalesOrderID, OrderDate, CustomerID, AccountNumber, TotalDue
FROM dbo.SillyView
ORDER BY CustomerID;

Vous obtenez les résultats triés comme vous le souhaitez :

SalesOrderID   OrderDate   CustomerID   AccountNumber   TotalDue
------------   ----------  ----------   --------------  ----------
43793          2005-07-22  11000        10-4030-011000  3756.989
51522          2007-07-22  11000        10-4030-011000  2587.8769
57418          2007-11-04  11000        10-4030-011000  2770.2682
51493          2007-07-20  11001        10-4030-011001  2674.0227
43767          2005-07-18  11001        10-4030-011001  3729.364

Et le plan a toujours optimisé le TOP /ORDER BY dans la vue, mais un tri est ajouté (à peu de frais, attention) pour présenter les résultats classés par CustomerID :

Donc, morale de l'histoire, ne mettez pas ORDER BY dans les vues. Mettez ORDER BY dans les requêtes qui y font référence. Et si le tri est coûteux, vous pouvez envisager d'ajouter/de modifier un index pour le prendre en charge.