Sqlserver
 sql >> база данни >  >> RDS >> Sqlserver

Създайте изглед с клауза ORDER BY

Не съм сигурен какво мислите за това ORDER BY се постига? Дори ако правите поставете ORDER BY в изгледа по законен начин (например чрез добавяне на TOP клауза), ако просто изберете от изгледа, напр. SELECT * FROM dbo.TopUsersTest; без ORDER BY клауза, SQL Server е свободен да връща редовете по най-ефективния начин, който не е задължително да съответства на реда, който очаквате. Това е така, защото ORDER BY е претоварен, тъй като се опитва да служи за две цели:да сортира резултатите и да диктува кои редове да се включат в TOP . В този случай TOP винаги печели (въпреки че в зависимост от индекса, избран за сканиране на данните, може да забележите, че поръчката ви работи според очакванията – но това е просто съвпадение).

За да постигнете това, което искате, трябва да добавите своя ORDER BY клауза към заявките, които изтеглят данни от изгледа, а не към кода на самия изглед.

Така че вашият изглед трябва да бъде просто:

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 е безсмислено, така че дори не трябва да се включва.

За илюстрация, използвайки AdventureWorks2012, ето един пример:

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;

Резултати:

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

И можете да видите от плана за изпълнение, че TOP и ORDER BY са били абсолютно игнорирани и оптимизирани от SQL Server:

Няма TOP оператор изобщо и без сортиране. SQL Server ги е оптимизирал напълно.

Сега, ако промените изгледа да кажете ORDER BY SalesID , тогава просто ще получите реда, който посочва изгледът, но само - както беше споменато по-горе - по съвпадение.

Но ако промените външната си заявка за изпълнение на ORDER BY искахте:

SELECT SalesOrderID, OrderDate, CustomerID, AccountNumber, TotalDue
FROM dbo.SillyView
ORDER BY CustomerID;

Получавате резултатите, подредени по желания от вас начин:

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

И планът все още оптимизира TOP /ORDER BY в изгледа, но се добавя сортиране (на не малка цена, имайте предвид), за да се представят резултатите, подредени по CustomerID :

Така че, морал на историята,не поставяйте ORDER BY в изгледите. Поставете ORDER BY в заявките, които ги препращат. И ако сортирането е скъпо, може да помислите за добавяне/промяна на индекс, за да го поддържате.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Всяка потребителска таблица трябва ли да има клъстериран индекс?

  2. Защо типът DATETIME на SQL Server спестява време в тикове от 1/300 от секундата?

  3. SQL - Изваждане на изчерпваща стойност от редове

  4. Свържете PHP към MSSQL чрез PDO ODBC

  5. Объркан относно UPDLOCK, HOLDLOCK