Sqlserver
 sql >> Database >  >> RDS >> Sqlserver

Crea una vista con la clausola ORDER BY

Non sono sicuro di cosa ne pensi questo ORDER BY sta realizzando? Anche se lo fai inserisci ORDER BY nella vista in modo legale (ad es. aggiungendo un TOP clausola), se si seleziona dalla vista, ad es. SELECT * FROM dbo.TopUsersTest; senza un ORDER BY clausola, SQL Server è libero di restituire le righe nel modo più efficiente, che non corrisponderà necessariamente all'ordine previsto. Questo perché ORDER BY è sovraccarico, in quanto cerca di servire a due scopi:ordinare i risultati e dettare quali righe includere in TOP . In questo caso, TOP vince sempre (anche se a seconda dell'indice scelto per scansionare i dati, potresti osservare che il tuo ordine funziona come previsto, ma questa è solo una coincidenza).

Per realizzare ciò che desideri, devi aggiungere il tuo ORDER BY clausola alle query che estraggono i dati dalla vista, non al codice della vista stessa.

Quindi il tuo codice di visualizzazione dovrebbe essere solo:

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

Il ORDER BY non ha senso, quindi non dovrebbe nemmeno essere incluso.

Per illustrare, utilizzando AdventureWorks2012, ecco un esempio:

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;

Risultati:

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

E puoi vedere dal piano di esecuzione che il TOP e ORDER BY sono stati assolutamente ignorati e ottimizzati da SQL Server:

Non c'è nessun TOP operatore a tutti e nessun ordinamento. SQL Server li ha ottimizzati completamente.

Ora, se cambi la visualizzazione per dire ORDER BY SalesID , ti capiterà di ottenere l'ordine indicato nella visualizzazione, ma solo - come accennato in precedenza - per coincidenza.

Ma se modifichi la tua query esterna per eseguire ORDER BY volevi:

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

Ottieni i risultati ordinati nel modo desiderato:

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

E il piano ha ancora ottimizzato il TOP /ORDER BY nella vista, ma viene aggiunto un ordinamento (a costo zero, intendiamoci) per presentare i risultati ordinati per CustomerID :

Quindi, morale della storia, non inserire ORDER BY nelle viste. Inserisci ORDER BY nelle query che li fanno riferimento. E se l'ordinamento è costoso, potresti considerare di aggiungere/modificare un indice per supportarlo.