RANK () và DENSE_RANK () có tính xác định hay không xác định?


27

Theo Microsoft BOL DENSE_RANK chính thức là không điều kiện ( RANK () ). Nhưng theo Chức năng xếp hạng của Itzik Ben-Gan "... các hàm RANK () và DENSE_RANK () luôn mang tính quyết định". Ai đúng?

Những gì tôi đã tìm thấy cho đến nay: Định nghĩa của Microsoft "Các hàm xác định luôn trả về cùng một kết quả bất cứ khi nào chúng được gọi với một bộ giá trị đầu vào cụ thể và được đưa ra cùng một trạng thái của cơ sở dữ liệu."

Vì vậy, trong bảng lý thuyết nhân viên

Employee            Salary
Sue Right            1.00
Robin Page           1.00
Phil Factor          1.00

và nhân viên2

Employee            Salary
Phil Factor          1.00
Sue Right            1.00
Robin Page           1.00

giống nhau. Nhưng các hàm Xếp hạng trả về các giá trị khác nhau:

    CREATE TABLE [dbo].[Employees](
    --[ID] [int] IDENTITY(1,1) NOT NULL,
    [Employee] [varchar](150) NOT NULL,
    [Salary] [smallmoney] NULL,
) ON [PRIMARY]

GO
CREATE TABLE [dbo].[Employees2](
    --[ID] [int] IDENTITY(1,1) NOT NULL,
    [Employee] [varchar](150) NOT NULL,
    [Salary] [smallmoney] NULL,
) ON [PRIMARY]

INSERT INTO [dbo].[Employees]
([Employee] ,[Salary])
VALUES
('Sue Right', 1)
, ('Robin Page', 1)
,('Phil Factor', 1 )
GO
INSERT INTO [dbo].[Employees2]
([Employee] ,[Salary])
VALUES
('Phil Factor', 1 )
,('Sue Right', 1)
,('Robin Page', 1)
GO
SELECT RANK() OVER ( ORDER BY Salary) AS [Rank]
, DENSE_RANK() OVER (ORDER BY Salary ) AS [Dense_rank]
, [Employee]
FROM
dbo.Employees

SELECT RANK() OVER ( ORDER BY Salary) AS [Rank]
, DENSE_RANK() OVER (ORDER BY Salary ) AS [Dense_rank]
, [Employee]
FROM
dbo.Employees2

SELECT NTILE(3) OVER ( ORDER BY SALARY )
, [Employee]
FROM
dbo.Employees

SELECT NTILE(3) OVER ( ORDER BY SALARY )
, [Employee]
FROM
dbo.Employees2

Câu trả lời:


23

Theo Microsoft BOL DENSE_RANK chính thức là không điều kiện (RANK ()). Nhưng theo Chức năng xếp hạng của Itzik Ben-Gan "... các hàm RANK () và DENSE_RANK () luôn mang tính quyết định". Ai đúng?

Cả hai đều đúng, bởi vì họ đang sử dụng các giác quan khác nhau của từ "xác định".

Từ quan điểm của trình tối ưu hóa SQL Server, "tính xác định" có ý nghĩa rất chính xác; một ý nghĩa tồn tại trước khi các chức năng cửa sổ và xếp hạng được thêm vào sản phẩm. Đối với trình tối ưu hóa, thuộc tính "xác định" xác định liệu một hàm có thể được sao chép tự do trong các cấu trúc cây bên trong của nó trong quá trình tối ưu hóa hay không. Điều này không hợp pháp cho một chức năng không xác định.

Xác định ở đây có nghĩa là: thể hiện chính xác của hàm luôn trả về cùng một đầu ra cho cùng một đầu vào, bất kể nó được gọi bao nhiêu lần. Điều này không bao giờ đúng đối với các hàm cửa sổ, theo định nghĩa, bởi vì là hàm vô hướng (một hàng), chúng không trả về cùng một kết quả trong một hàng hoặc trên các hàng. Nói một cách đơn giản, sử dụng ROW_NUMBERlàm ví dụ:

Các ROW_NUMBERhàm trả về giá trị khác nhau cho các hàng khác nhau (theo định nghĩa!), Do đó cho mục đích tối ưu hóa nó là không xác định

Đây là ý nghĩa BOL đang sử dụng.

Itzik đang đưa ra một quan điểm khác nhau về tính quyết định của kết quả nói chung. Trong một tập hợp đầu vào có thứ tự (với sự phá vỡ phù hợp), đầu ra là một chuỗi "xác định". Đó là một quan sát hợp lệ, nhưng nó không phải là chất lượng "xác định" mà quan trọng trong quá trình tối ưu hóa truy vấn.


10

NTILE()là một trường hợp thú vị; nó dường như được áp dụng sau khi sắp xếp (trong trường hợp hòa, được để lại cho các thiết bị của SQL Server và điều này thường được điều khiển bởi sự lựa chọn chỉ mục hiệu quả nhất cho mục đích sắp xếp). Bạn có thể đưa ra quyết định này bằng cách không buộc SQL Server đưa ra lựa chọn tùy ý ở đây - thêm một hoặc nhiều bộ ngắt kết nối vào OVER()mệnh đề:

OVER (ORDER BY Salary, Employee)

Về cơ bản bạn cần phải làm cho việc phân loại độc đáo. Nếu bạn có nhân viên có cùng tên, bạn có thể phải chọn một cột ngắt kết nối khác hoặc tiếp tục thêm các cột cho đến khi thực sự không thể có mối quan hệ nào.

Đối với RANK()DENSE_RANK(), mối quan hệ thực sự là một lý do quan trọng mà bạn không thể có được các giá trị khác nhau. Cố gắng không nhầm lẫn tính xác định của đầu ra của hàm với tính xác định của thứ tự kết quả. Nếu các truy vấn của bạn không có ORDER BY, thì điều gì không xác định về điều này?

1   1   Sue Right
1   1   Robin Page
1   1   Phil Factor

1   1   Phil Factor
1   1   Sue Right
1   1   Robin Page

RANK()DENSE_RANK()áp dụng các giá trị giống nhau trong cả hai trường hợp, SQL Server chỉ trả về kết quả cho bạn theo một thứ tự khác. Điều này không liên quan gì đến việc mong đợi cùng một đầu ra từ RANK()hoặc DENSE_RANK()đưa ra cùng một đầu vào - đây chỉ là giả định hoặc mong đợi một số thứ tự xác định khi bạn nói với SQL Server (bằng cách bỏ qua một ORDER BYmệnh đề) mà bạn không quan tâm đến thứ tự của kết quả. Xem # 3 tại đây:


7

Cú pháp:

WindowFunction() OVER (PARTITION BY <some expressions>        -- partition list
                       ORDER BY <some other expressions>)     -- order list

Cả hai hàm RANK()DENSE_RANK()theo định nghĩa của chúng đều được đảm bảo tạo ra cùng một kết quả miễn là các biểu thức trong OVERmệnh đề là chính xác định. Và đó là ý nghĩa của Itzik Ben-Gun trong bài viết của mình. Những danh sách này thường chỉ là các cột của các bảng liên quan.

Vì vậy, trong khi các hàm nói chung không mang tính quyết định, thì việc thực hiện chúng có thể được quan tâm để phân biệt hai trường hợp và xem xét chúng có xác định hay không, khi kiểm tra danh sách phân vùng và thứ tự.

Tôi đoán, là các nhà phát triển SQL-Server đã quyết định thực hiện chúng dễ dàng hơn vì luôn luôn "không xác định" mặc dù điều này mâu thuẫn theo cách định nghĩa của chúng về các hàm xác định. Vì vậy, chúng được tuyên bố là không xác định trong MSDN bởi vì trong triển khai hiện tại, công cụ coi chúng luôn luôn là không xác định.

Một đối số nữa là hai hàm cửa sổ khác, ROW_NUMBER()NTILE()thậm chí còn phức tạp hơn vì đối với chúng có đầu ra giống hệt nhau, biểu thức trong phân vùng và thứ tự theo danh sách không chỉ phải xác định mà còn duy nhất. Vì vậy, thực hiện tất cả những chi tiết đó là xa tầm thường.


Tôi sẽ không bình luận về thứ tự của các tập kết quả, vì điều này không liên quan gì đến tính quyết định, vì Aaron Bertrand đã giải thích rõ ràng trong câu trả lời của mình.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.