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.