Jeg er ikke sikker på, hvad du synes om denne ORDER BY
udfører? Også selvom du gør angiv ORDER BY
i visningen på en lovlig måde (f.eks. ved at tilføje en TOP
klausul), hvis du blot vælger fra visningen, f.eks. SELECT * FROM dbo.TopUsersTest;
uden en ORDER BY
klausul, er SQL Server fri til at returnere rækkerne på den mest effektive måde, som ikke nødvendigvis matcher den rækkefølge, du forventer. Dette er fordi ORDER BY
er overbelastet, idet den forsøger at tjene to formål:at sortere resultaterne og at diktere, hvilke rækker der skal inkluderes i TOP
. I dette tilfælde TOP
vinder altid (selvom afhængigt af det valgte indeks til at scanne dataene, kan du måske observere, at din ordre fungerer som forventet - men dette er kun en tilfældighed).
For at opnå det, du ønsker, skal du tilføje din ORDER BY
klausul til de forespørgsler, der trækker data fra visningen, ikke til koden for selve visningen.
Så din visningskode skal bare være:
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
er meningsløst, så bør ikke engang inkluderes.
For at illustrere, ved hjælp af AdventureWorks2012, er her et eksempel:
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;
Resultater:
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
Og du kan se fra udførelsesplanen, at TOP
og ORDER BY
er blevet fuldstændig ignoreret og optimeret væk af SQL Server:
Der er ingen TOP
operatør overhovedet, og ingen slags. SQL Server har optimeret dem helt væk.
Nu, hvis du ændrer visningen til at sige ORDER BY SalesID
, vil du så tilfældigvis få den rækkefølge, som visningen angiver, men kun - som før nævnt - ved et tilfælde.
Men hvis du ændrer din ydre forespørgsel til at udføre ORDER BY
du ønskede:
SELECT SalesOrderID, OrderDate, CustomerID, AccountNumber, TotalDue
FROM dbo.SillyView
ORDER BY CustomerID;
Du får resultaterne ordnet, som du ønsker:
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
Og planen har stadig optimeret TOP
væk /ORDER BY
i visningen, men der tilføjes en sortering (uden små omkostninger, vel at mærke) for at præsentere resultaterne sorteret efter CustomerID
:
Så, moralsk i historien, sæt ikke ORDER BY i visninger. Angiv ORDER BY i de forespørgsler, der refererer til dem. Og hvis sorteringen er dyr, kan du overveje at tilføje/ændre et indeks for at understøtte det.