SELECT ROW_NUMBER () รับประกันว่าจะให้ผลลัพธ์ที่เรียงลำดับตามหมายเลขแถวที่สร้างขึ้นหรือไม่


10

เช่นพิจารณาแบบสอบถาม SQL:

SELECT
   A.[Name],
   ROW_NUMBER() OVER(ORDER BY A.[Name] ASC)
FROM
   [FooTable] AS A

ที่นี่ฉันสังเกตเห็นผลลัพธ์ที่ถูกส่งคืนโดย A. [ชื่อ] หากฉันเปลี่ยนคอลัมน์เรียงลำดับที่กำหนดไว้ในฟังก์ชัน ROW_NUMBER เป็นคอลัมน์อื่นผลลัพธ์จะกลายเป็นคอลัมน์เรียงลำดับอีกครั้ง

ฉันคาดหวังว่าหมายเลขแถวจะถูกกำหนดให้กับแถว แต่ฉันไม่ได้คาดหวังว่าแถวจะกลับมาเรียงตามเกณฑ์เดียวกัน นี่เป็นเพียงผลข้างเคียงของวิธีการดำเนินการค้นหา (ในกรณีของฉันใน SQL Server 2008 R2) หรือพฤติกรรมนี้รับประกันได้หรือไม่ (ฉันไม่พบการอ้างอิงถึงการรับประกันดังกล่าว)


10
ไม่เคยรับประกันใด ๆ เคย ถ้าคุณไม่บอกให้ SQL Server ทราบถึงวิธีการสั่งซื้อสินค้าคุณสามารถส่งคืนข้อมูลตามลำดับที่ต้องการ เมื่อออกจากการสั่งซื้อคุณกำลังบอก SQL Server ว่าคุณไม่สนใจเกี่ยวกับการสั่งซื้อ หากคุณต้องการการรับประกันให้พิมพ์คำสั่งย่อย ORDER BY แล้ว
Aaron Bertrand

มีเหตุผลที่ดีสำหรับการถามเนื่องจากคำสั่งตามคำถามมีความซับซ้อนมากดังนั้นการคัดลอกจะสร้างบัลลาสต์การบำรุงรักษาโค้ดรวมทั้งเพิ่มโอกาสในการเกิดข้อบกพร่องในอนาคต อีกทางเลือกหนึ่งคือการเปลี่ยนโครงสร้างเล็กน้อยซึ่งฉันคิดว่าฉันอาจหลีกเลี่ยงได้หากมาตรฐาน SQL กำหนดลำดับการจัดเรียงโดยนัย ไม่ว่าในกรณีใดฉันแค่สนใจว่ามีเอกสารที่เป็นทางการครอบคลุมประเด็นนี้
redcalx

1
ดังนั้นทำไมไม่ถามคำถามนั้น
Aaron Bertrand

คำตอบ:


14

หากคุณเคยถามคำถามฉันคิดว่าคุณตั้งใจจะถามจริง:

ฉันจะสั่งซื้อโดยROW_NUMBER()ไม่ต้องทำซ้ำORDER BYนิพจน์ที่ซับซ้อนได้อย่างไร

เราอาจบอกให้คุณสร้างนามแฝงสำหรับROW_NUMBER()นิพจน์แล้วเรียงลำดับโดยใช้นามแฝง:

SELECT
   A.[Name],
   rn = ROW_NUMBER() OVER (ORDER BY <complex expression>)
FROM
   dbo.[FooTable] AS A
ORDER BY rn;

ตอนนี้คุณต้องเปลี่ยนการแสดงออกในที่เดียวและการเรียงลำดับผลลัพธ์จะขึ้นอยู่กับการแสดงออกนั้นโดยไม่ต้องทำซ้ำ


6
ที่จริงแล้วrepeating the complex ORDER BY expressionไม่รับประกันว่าผลลัพธ์จะออกมาตามคำสั่ง ROW_NUMBER () เว้นแต่คอลัมน์ในส่วนคำสั่ง ORDER BY จะสร้างคีย์ที่ไม่ซ้ำกัน
孔夫子

22

ไม่ได้อย่างแน่นอน. พิสูจน์:

SELECT
   A.[Name],
   ROW_NUMBER() OVER(ORDER BY A.[Name] ASC),
   ROW_NUMBER() OVER(ORDER BY A.[Name] DESC)
FROM
   [FooTable] AS A

วิธีเดียวที่จะรับประกันการสั่งซื้อใน SQL คือการขอให้ใช้ ORDER BYกับผลลัพธ์เอง


ตกลงฉันจะเพิ่มคุณสมบัติอีกหนึ่งข้อ - เป็นผลลัพธ์ที่รับประกันว่าจะถูกจัดเรียงหากระบุ ROW_NUMBER () ข้อเดียวเท่านั้น
redcalx

22
วิธีเดียวที่จะรับประกันการสั่งซื้อใน SQL คือการขอให้มัน
Remus Rusanu

0

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

ดังนั้นจึงไม่ง่ายอย่างที่บางคนแนะนำให้กำหนด row_number และใช้สำหรับการสั่งซื้อ

เราจะต้อง sql ที่ซ้อนกันในการแยกพาร์ทิชันโดยข้อเช่นกัน (ถ้าเราไม่ต้องการที่จะทำซ้ำมันแน่นอน)

สังเกตุเราดูเหมือนจะได้รับบรรทัดสุดท้ายของการสั่งซื้อโดยปริยาย

Select
  <field-list>, 
  rn=Row_Number() over(partition by <PartionClause>) order by <OrderClause>
from ....
Order by <PartionClause> asc, rn asc

แต่สิ่งที่เราขาดคือหลักฐานหรือการรับประกันใด ๆ ว่ามันมีอยู่เสมอ

(หากมีการเรียก Row_Number () หลายครั้งการโทรมันเป็นครั้งสุดท้ายที่ดูเหมือนว่าจะสั่งซื้อ)

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


1
สิ่งนี้ไม่ได้ตอบคำถามจริงๆและดูเหมือนจะไม่เห็นด้วยกับคำตอบที่ยอมรับและคำตอบที่ได้รับการตอบกลับอย่างสูง
Erik ดาร์ลิ่ง

ฉันยอมรับว่าของฉันมีความคิดเห็นมากกว่าคำตอบ คำตอบที่ได้รับการยอมรับนั้นไม่ใช่คำตอบจริงๆยกเว้นมันบอกว่าเราไม่ควรไว้ใจคำสั่งซื้อ - และนั่นคือคำถาม มันสามารถเห็นได้จากแผนการดำเนินการที่จริง ๆ แล้วมันเป็นการเรียงลำดับและถ้าเราเพิ่มคำสั่งที่ชัดเจนโดยเราจะได้รับการเรียงลำดับที่สอง แต่นั่นไม่ใช่ข้อพิสูจน์มันเป็นเพียงส่วนหนึ่งของความรู้เชิงประจักษ์
Eske Rahn

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