Sqlserver
 sql >> Baza danych >  >> RDS >> Sqlserver

Utwórz widok z klauzulą ​​ORDER BY

Nie jestem pewien, co myślisz to ORDER BY realizuje się? Nawet jeśli robisz umieść ORDER BY w widoku w sposób legalny (np. przez dodanie TOP klauzuli), jeśli po prostu wybierzesz z widoku np. SELECT * FROM dbo.TopUsersTest; bez ORDER BY SQL Server może zwracać wiersze w najbardziej efektywny sposób, który niekoniecznie będzie odpowiadał oczekiwanej kolejności. Dzieje się tak, ponieważ ORDER BY jest przeciążony, ponieważ próbuje służyć dwóm celom:sortowaniu wyników i dyktowaniu, które wiersze należy uwzględnić w TOP . W tym przypadku TOP zawsze wygrywa (chociaż w zależności od indeksu wybranego do skanowania danych możesz zauważyć, że Twoje zamówienie działa zgodnie z oczekiwaniami - ale to tylko zbieg okoliczności).

Aby osiągnąć to, czego chcesz, musisz dodać swoje ORDER BY klauzula do zapytań, które pobierają dane z widoku, a nie do kodu samego widoku.

Twój kod widoku powinien wyglądać tak:

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

ORDER BY jest bez znaczenia, więc nie powinno być nawet uwzględnione.

Aby zilustrować, używając AdventureWorks2012, oto przykład:

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;

Wyniki:

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

A z planu wykonania widać, że TOP i ORDER BY zostały całkowicie zignorowane i zoptymalizowane przez SQL Server:

Nie ma TOP w ogóle operatora i bez sortowania. SQL Server całkowicie je zoptymalizował.

Teraz, jeśli zmienisz widok na ORDER BY SalesID , zdarzy się, że uzyskasz kolejność określoną w widoku, ale tylko - jak wspomniano wcześniej - przez przypadek.

Ale jeśli zmienisz zapytanie zewnętrzne, aby wykonać ORDER BY chciałeś:

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

Otrzymasz wyniki uporządkowane tak, jak chcesz:

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

A plan nadal zoptymalizował TOP /ORDER BY w widoku, ale dodaje się sortowanie (przypominam, że niewielkim kosztem), aby przedstawić wyniki uporządkowane według CustomerID :

Tak więc, morał z tej historii, nie umieszczaj ORDER BY w widokach. Umieść ORDER BY w zapytaniach, które do nich się odnoszą. A jeśli sortowanie jest drogie, możesz rozważyć dodanie/zmianę indeksu w celu jego obsługi.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Czy istnieje sposób na uzyskanie listy wszystkich aktualnych tabel tymczasowych w SQL Server?

  2. Konwersja typu danych datetime2 na typ danych datetime wynika z wartości spoza zakresu

  3. Czy można połączyć wartości kolumn w ciąg znaków za pomocą CTE?

  4. Jak usunąć z wielu tabel za pomocą INNER JOIN na serwerze SQL?

  5. jak zapisać liczbę do funkcji słowa w serwerze sql