RANK () และ DENSE_RANK () กำหนดขึ้นหรือไม่ได้กำหนดไว้หรือไม่


27

ตามBOL DENSE_RANK อย่างเป็นทางการของ Microsoftเป็น nondeterministic ( RANK () ) แต่ตามฟังก์ชั่นการจัดอันดับโดย Itzik Ben-Gan "... ฟังก์ชั่น RANK () และ DENSE_RANK () นั้นมักจะถูกกำหนด" ถูกต้องใคร

สิ่งที่ฉันได้ค้นพบแล้ว: นิยามของ Microsoft "ฟังก์ชันกำหนดค่าจะส่งคืนผลลัพธ์เดียวกันทุกครั้งที่มีการเรียกใช้ด้วยชุดค่าอินพุตเฉพาะและกำหนดสถานะของฐานข้อมูลเดียวกัน"

ดังนั้นใน Set ทฤษฎีตารางพนักงาน

Employee            Salary
Sue Right            1.00
Robin Page           1.00
Phil Factor          1.00

และพนักงาน 2

Employee            Salary
Phil Factor          1.00
Sue Right            1.00
Robin Page           1.00

เหมือนกัน. แต่ฟังก์ชั่นการจัดอันดับกลับค่าที่แตกต่าง:

    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

คำตอบ:


23

ตาม BOL DENSE_RANK อย่างเป็นทางการของ Microsoft เป็น nondeterministic (RANK ()) แต่ตามฟังก์ชั่นการจัดอันดับโดย Itzik Ben-Gan "... ฟังก์ชั่น RANK () และ DENSE_RANK () นั้นมักจะถูกกำหนด" ถูกต้องใคร

พวกเขาทั้งคู่ถูกต้องเพราะพวกเขาใช้ประสาทสัมผัสที่แตกต่างกันของคำว่า "deterministic"

จากมุมมองของเครื่องมือเพิ่มประสิทธิภาพ SQL Server "deterministic" มีความหมายที่แม่นยำมาก ความหมายที่มีอยู่ก่อนฟังก์ชั่นหน้าต่างและการจัดอันดับถูกเพิ่มเข้าไปในผลิตภัณฑ์ สำหรับเครื่องมือปรับแต่งคุณสมบัติ "กำหนดค่า" กำหนดว่าฟังก์ชันสามารถทำซ้ำได้อย่างอิสระภายในโครงสร้างแผนผังภายในระหว่างการปรับให้เหมาะสมหรือไม่ สิ่งนี้ไม่ถูกกฎหมายสำหรับฟังก์ชันที่ไม่ได้กำหนดไว้

กำหนดได้ที่นี่หมายถึง: อินสแตนซ์ที่แน่นอนของฟังก์ชันจะส่งคืนเอาต์พุตเดียวกันสำหรับอินพุตเดียวกันเสมอไม่ว่าจะถูกเรียกใช้กี่ครั้งก็ตาม สิ่งนี้ไม่เป็นความจริงสำหรับฟังก์ชั่นหน้าต่างตามนิยามเนื่องจากในฐานะที่เป็นฟังก์ชันสเกลาร์ (แถวเดียว) ฟังก์ชันจะไม่ส่งคืนผลลัพธ์เดียวกันภายในแถวหรือข้ามแถว ในการระบุอย่างง่าย ๆ ให้ใช้ROW_NUMBERเป็นตัวอย่าง:

ROW_NUMBERฟังก์ชันส่งกลับค่าที่แตกต่างกันสำหรับแถวที่แตกต่างกัน (ตามคำนิยาม!) ดังนั้นสำหรับวัตถุประสงค์ในการเพิ่มประสิทธิภาพมันเป็น nondeterministic

นี่คือความรู้สึกที่ใช้ BOL

Itzik กำลังสร้างประเด็นที่แตกต่างเกี่ยวกับระดับของผลลัพธ์โดยรวม เหนือชุดอินพุตที่เรียงลำดับแล้ว (ที่มีการผูกไทม์ที่เหมาะสม) เอาต์พุตจะเป็นลำดับ "กำหนดขึ้นได้" นั่นคือการสังเกตที่ถูกต้อง แต่ไม่ใช่คุณภาพ "กำหนด" ที่สำคัญในระหว่างการปรับให้เหมาะสมของแบบสอบถาม


10

NTILE()เป็นกรณีที่น่าสนใจ ดูเหมือนว่าจะนำไปใช้หลังจากการเรียงลำดับ (ซึ่งในกรณีของการเสมอกันจะถูกปล่อยไว้ที่อุปกรณ์ของ SQL Server และมักจะถูกขับเคลื่อนด้วยตัวเลือกดัชนีที่มีประสิทธิภาพที่สุดสำหรับการเรียงลำดับ) คุณสามารถกำหนดสิ่งนี้ได้โดยไม่บังคับให้ SQL Server เลือกตัวเลือกเองที่นี่ - เพิ่มตัวแบ่งเบรกเกอร์อย่างน้อยหนึ่งตัวในOVER()ข้อ:

OVER (ORDER BY Salary, Employee)

เป็นหลักคุณจะต้องทำให้การเรียงลำดับที่ไม่ซ้ำ หากคุณมีพนักงานที่มีชื่อเดียวกันคุณอาจต้องเลือกคอลัมน์ tie-breaker อื่น ๆ หรือเพิ่มคอลัมน์ต่อไปเรื่อย ๆ จนกว่าจะไม่มีความสัมพันธ์ใด ๆ

สำหรับRANK()และDENSE_RANK()ความสัมพันธ์เป็นเหตุผลสำคัญที่คุณไม่สามารถรับค่าที่แตกต่างกัน พยายามอย่าสับสนระดับเอาท์พุทของฟังก์ชั่นด้วยการกำหนดลำดับของผลลัพธ์ หากคำถามของคุณไม่มีORDER BYแล้วอะไรที่ไม่ได้กำหนดเกี่ยวกับเรื่องนี้?

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()ใช้ค่าเดียวกันในทั้งสองกรณี SQL Server เพิ่งส่งคืนผลลัพธ์ให้คุณในลำดับที่แตกต่างกัน สิ่งนี้ไม่เกี่ยวกับการคาดหวังผลลัพธ์ที่เหมือนกันจากRANK()หรือDENSE_RANK()ได้รับอินพุตเดียวกัน - นี่เป็นเพียงการสมมติหรือคาดหวังคำสั่งที่กำหนดเมื่อคุณบอกกับ SQL Server (โดยไม่ต้องใส่ORDER BYประโยค) ที่คุณไม่สนใจเกี่ยวกับลำดับของ ผลลัพธ์ ดู # 3 ที่นี่:


7

ไวยากรณ์:

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

ทั้งฟังก์ชั่นRANK()และDENSE_RANK()ตามคำจำกัดความของพวกเขารับประกันว่าจะให้ผลลัพธ์ที่เหมือนกันตราบใดที่การแสดงออกในOVERข้อที่กำหนดเอง และนั่นคือสิ่งที่ Itzik Ben-Gun มีความหมายในบทความของเขา รายการเหล่านี้ส่วนใหญ่มักจะเป็นเพียงคอลัมน์ของตารางที่เกี่ยวข้อง

ดังนั้นในขณะที่ฟังก์ชั่นทั่วไปไม่ได้กำหนดไว้ แต่การใช้งานของพวกเขาอาจได้รับการดูแลเพื่อแยกความแตกต่างของทั้งสองกรณีและพิจารณาพวกเขากำหนดขึ้นหรือไม่เมื่อตรวจสอบพาร์ทิชันและรายการสั่งซื้อ

การคาดเดาที่ฉับพลันของฉันคือผู้พัฒนา SQL-Server ตัดสินใจว่าจะง่ายต่อการปรับใช้พวกเขาเช่นเคย "ไม่ได้กำหนดไว้" แม้จะขัดแย้งกับวิธีการนิยามฟังก์ชันการทำงานที่กำหนดไว้ ดังนั้นพวกมันจึงถูกระบุว่าไม่สามารถกำหนดได้ใน MSDN เพราะในการนำไปใช้ในปัจจุบันเอ็นจิ้นจะพิจารณาว่ามันไม่เป็นตัวกำหนด

อีกข้อโต้แย้งก็คืออีกฟังก์ชันของหน้าต่างสองบานROW_NUMBER()และNTILE()มีความซับซ้อนมากขึ้นเพราะพวกมันมีเอาท์พุทที่เหมือนกันนิพจน์ในพาร์ติชั่นและการเรียงลำดับตามรายการไม่เพียง แต่จะต้องกำหนดขึ้นมาเท่านั้น ดังนั้นการใช้รายละเอียดทั้งหมดเหล่านี้จึงไม่ใช่เรื่องง่าย


ฉันจะไม่แสดงความคิดเห็นเกี่ยวกับลำดับของชุดผลลัพธ์เนื่องจากไม่มีส่วนเกี่ยวข้องกับระดับที่กำหนดเนื่องจากแอรอนเบอร์ทรานด์ได้อธิบายไว้อย่างชัดเจนในคำตอบของเขา

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.