sql >> Base de Datos >  >> RDS >> Sqlserver

Crear una vista con la cláusula ORDER BY

No estoy seguro de lo que piensas de este ORDER BY esta logrando? Incluso si haces poner ORDER BY en la vista de forma legal (por ejemplo, agregando un TOP cláusula), si solo selecciona de la vista, p. SELECT * FROM dbo.TopUsersTest; sin ORDER BY cláusula, SQL Server es libre de devolver las filas de la manera más eficiente, que no necesariamente coincidirá con el orden que espera. Esto se debe a que ORDER BY está sobrecargado, ya que intenta cumplir dos propósitos:ordenar los resultados y dictar qué filas incluir en TOP . En este caso, TOP siempre gana (aunque dependiendo del índice elegido para escanear los datos, es posible que observe que su pedido funciona como se esperaba, pero esto es solo una coincidencia).

Para lograr lo que desea, debe agregar su ORDER BY cláusula a las consultas que extraen datos de la vista, no al código de la vista en sí.

Entonces su código de vista debería ser:

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];

El ORDER BY no tiene sentido, por lo que ni siquiera debería incluirse.

Para ilustrar, usando AdventureWorks2012, aquí hay un ejemplo:

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;

Resultados:

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

Y puede ver en el plan de ejecución que TOP y ORDER BY han sido absolutamente ignorados y optimizados por SQL Server:

No hay TOP operador en absoluto, y ningún tipo. SQL Server los ha optimizado completamente.

Ahora, si cambia la vista para decir ORDER BY SalesID , simplemente obtendrá el orden que indica la vista, pero solo, como se mencionó anteriormente, por coincidencia.

Pero si cambia su consulta externa para realizar el ORDER BY querías:

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

Obtienes los resultados ordenados de la forma que quieras:

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

Y el plan todavía ha optimizado el TOP /ORDER BY en la vista, pero se agrega una clasificación (a un costo no pequeño, eso sí) para presentar los resultados ordenados por CustomerID :

Entonces, la moraleja de la historia, no pongas ORDER BY en vistas. Escriba ORDER BY en las consultas que los referencian. Y si la clasificación es costosa, podría considerar agregar/cambiar un índice para admitirlo.