Sqlserver
 sql >> Cơ Sở Dữ Liệu >  >> RDS >> Sqlserver

Tạo chế độ xem với mệnh đề ORDER BY

Tôi không chắc bạn nghĩ gì về điều này ORDER BY đang hoàn thành? Ngay cả khi bạn làm đặt ORDER BY trong chế độ xem theo cách hợp pháp (ví dụ:bằng cách thêm TOP mệnh đề), nếu bạn chỉ chọn từ chế độ xem, ví dụ:SELECT * FROM dbo.TopUsersTest; không có ORDER BY , SQL Server miễn phí trả về các hàng theo cách hiệu quả nhất, không nhất thiết phải khớp với thứ tự bạn mong đợi. Điều này là do ORDER BY bị quá tải, trong đó nó cố gắng phục vụ hai mục đích:sắp xếp kết quả và chỉ định những hàng nào cần đưa vào TOP . Trong trường hợp này, TOP luôn thắng (mặc dù tùy thuộc vào chỉ mục được chọn để quét dữ liệu, bạn có thể thấy rằng đơn đặt hàng của mình đang hoạt động như mong đợi - nhưng đây chỉ là sự trùng hợp ngẫu nhiên).

Để đạt được những gì bạn muốn, bạn cần thêm ORDER BY của mình mệnh đề cho các truy vấn lấy dữ liệu từ chế độ xem, không phải mã của chính chế độ xem.

Vì vậy, mã chế độ xem của bạn chỉ nên là:

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 là vô nghĩa vì vậy thậm chí không nên đưa vào.

Để minh họa bằng cách sử dụng AdventureWorks2012, đây là một ví dụ:

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;

Kết quả:

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

Và bạn có thể thấy từ kế hoạch thực thi rằng TOPORDER BY đã hoàn toàn bị SQL Server bỏ qua và tối ưu hóa:

Không có TOP toán tử ở tất cả, và không có phân loại. SQL Server đã tối ưu hóa chúng hoàn toàn.

Bây giờ, nếu bạn thay đổi chế độ xem để nói ORDER BY SalesID , sau đó bạn sẽ chỉ tình cờ nhận được thứ tự mà chế độ xem nêu ra, nhưng chỉ - như đã đề cập trước đây - một cách trùng hợp.

Nhưng nếu bạn thay đổi truy vấn bên ngoài của mình để thực hiện ORDER BY bạn muốn:

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

Bạn nhận được kết quả được sắp xếp theo cách bạn muốn:

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

Và kế hoạch vẫn tối ưu hóa TOP / ORDER BY trong chế độ xem, nhưng một sắp xếp được thêm vào (với chi phí không nhỏ, bạn nhớ nhé) để trình bày kết quả được sắp xếp theo CustomerID :

Vì vậy, đạo lý của câu chuyện, không đặt ORDER BY trong các lượt xem. Đặt ORDER BY trong các truy vấn tham chiếu đến chúng. Và nếu việc phân loại là tốn kém, bạn có thể xem xét thêm / thay đổi một chỉ mục để hỗ trợ nó.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Làm cách nào tôi có thể xem tất cả các ký tự đặc biệt được phép trong trường varchar hoặc char trong SQL Server?

  2. Làm cách nào để tôi có thể bước vào một chương trình SQL Server được lưu trữ từ mã C # của tôi?

  3. Trả lại Tên máy trạm hiện tại được kết nối với SQL Server (T-SQL)

  4. Lỗi trong SQL Server khi nhập tệp CSV mặc dù varchar (MAX) được sử dụng cho mỗi cột

  5. Tập lệnh được cải tiến trả về tất cả các thuộc tính từ SERVERPROPERTY () trong SQL Server