sql >> Databáze >  >> RDS >> Sqlserver

Vytvořte pohled s klauzulí ORDER BY

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.



  1. Najít nečíselné hodnoty ve sloupci na serveru SQL Server

  2. Používání relačních databází MySQL na Gentoo

  3. Vytvoření uživatele na MySQL

  4. 4 způsoby, jak zabránit přetížení výstrah pomocí monitorování serveru SQL