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

Opret en visning med ORDER BY-klausul

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.



  1. Kan IN-operatøren bruge LIKE-wildcards (%) i Oracle?

  2. Returner rækker, der indeholder ikke-alfanumeriske tegn i SQL Server

  3. Hvordan gemmer man flere muligheder i en enkelt tabel?

  4. Fastgør tabel i Flash-cachen