Nejsem si jistý, co si myslíte o tomto ORDER BY
plní? I když děláte zadejte ORDER BY
v pohledu legální cestou (např. přidáním TOP
klauzule), pokud pouze vyberete z pohledu, např. SELECT * FROM dbo.TopUsersTest;
bez ORDER BY
klauzule SQL Server může řádky vracet nejefektivnějším způsobem, který nemusí nutně odpovídat očekávanému pořadí. Důvodem je ORDER BY
je přetížený v tom, že se snaží sloužit dvěma účelům:třídit výsledky a diktovat, které řádky zahrnout do TOP
. V tomto případě TOP
vždy vyhraje (ačkoli v závislosti na indexu zvoleném pro skenování dat můžete pozorovat, že vaše objednávka funguje podle očekávání – ale to je jen náhoda).
Abyste dosáhli toho, co chcete, musíte přidat svůj ORDER BY
klauzule na dotazy, které vytahují data ze zobrazení, nikoli na kód samotného zobrazení.
Váš kód zobrazení by tedy měl být:
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
je nesmyslné, takže by nemělo být ani zahrnuto.
Pro ilustraci, použití AdventureWorks2012, zde je příklad:
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;
Výsledky:
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 prováděcího plánu můžete vidět, že TOP
a ORDER BY
byly absolutně ignorovány a optimalizovány SQL Serverem:
Neexistuje žádný TOP
operátor vůbec a bez řazení. SQL Server je zcela optimalizoval.
Pokud nyní změníte zobrazení na ORDER BY SalesID
, pak jen náhodou dostanete pořadí, které uvádí pohled, ale pouze - jak již bylo zmíněno - shodou okolností.
Pokud ale změníte svůj vnější dotaz tak, aby prováděl ORDER BY
chtěl jsi:
SELECT SalesOrderID, OrderDate, CustomerID, AccountNumber, TotalDue
FROM dbo.SillyView
ORDER BY CustomerID;
Výsledky získáte tak, jak chcete:
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 plán stále optimalizuje TOP
/ORDER BY
v zobrazení, ale je přidáno řazení (za žádnou malou cenu, pamatujte na to), aby byly zobrazeny výsledky seřazené podle CustomerID
:
Takže, morálka příběhu, nedávejte ORDER BY do zobrazení. Do dotazů, které na ně odkazují, zadejte ORDER BY. A pokud je třídění drahé, můžete zvážit přidání/změnu indexu, aby jej podporoval.