Apakah SELECT ROW_NUMBER () dijamin untuk mengembalikan hasil yang diurutkan berdasarkan nomor baris yang dihasilkan?

10

Misalnya, pertimbangkan permintaan SQL:

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

Di sini saya amati hasil yang dikembalikan diurutkan berdasarkan A. [Nama]. Jika saya mengubah kolom sortir yang didefinisikan dalam fungsi ROW_NUMBER ke kolom lain, sekali lagi hasilnya menjadi diurutkan berdasarkan kolom itu.

Saya mengharapkan nomor baris untuk ditugaskan ke baris tetapi saya tidak mengharapkan baris untuk kembali diurutkan berdasarkan kriteria yang sama. Apakah ini hanya efek samping dari bagaimana kueri dieksekusi (dalam kasus saya di SQL Server 2008 R2) atau apakah perilaku ini dijamin? (Saya tidak dapat menemukan referensi untuk jaminan semacam itu).

redcalx
sumber
10
Tidak pernah ada jaminan. Pernah. Kecuali Anda memberi tahu SQL Server cara memesan sesuatu, itu bebas untuk mengembalikan data dalam urutan apa pun yang diinginkan. Dengan meninggalkan pesanan, Anda memberi tahu SQL Server bahwa Anda tidak peduli dengan pesanan. Jika Anda menginginkan jaminan, cukup ketik klausa ORDER BY.
Aaron Bertrand
Ada alasan yang bagus untuk bertanya karena klausa urutan-per pertanyaan yang ada sangat kompleks dan oleh karena itu penyalinan akan menciptakan balast pemeliharaan kode sekaligus meningkatkan kemungkinan cacat di masa mendatang. Alternatif lain adalah refactoring minor yang saya pikir saya mungkin bisa hindari jika standar SQL mendefinisikan urutan sortir implisit. Bagaimanapun saya hanya tertarik jika ada dokumentasi formal yang membahas hal ini.
redcalx
1
jadi mengapa tidak mengajukan pertanyaan itu?
Aaron Bertrand

Jawaban:

14

Jika Anda mengajukan pertanyaan, saya pikir Anda sebenarnya bermaksud untuk bertanya:

Bagaimana saya bisa memesan ROW_NUMBER()tanpa mengulangi ORDER BYekspresi kompleks ?

Kami dapat memberi tahu Anda untuk membuat alias untuk ROW_NUMBER()ekspresi, lalu mengurutkan menggunakan alias:

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

Sekarang Anda hanya perlu mengubah ekspresi di satu tempat, dan jenis yang dihasilkan akan didasarkan pada ekspresi itu tanpa harus mengulanginya.

Aaron Bertrand
sumber
6
Bahkan, repeating the complex ORDER BY expressionbahkan tidak menjamin output akan keluar berdasarkan pesanan ROW_NUMBER (). Kecuali jika kolom dalam klausa ORDER BY membentuk kunci unik.
孔夫子
22

Benar-benar tidak. Bukti:

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

Satu-satunya cara untuk menjamin pesanan dalam SQL adalah dengan memintanya, gunakan ORDER BYpada hasilnya sendiri.

Remus Rusanu
sumber
OK saya akan menambahkan satu kualifikasi lebih lanjut - apakah hasilnya dijamin akan diurutkan jika hanya satu klausa ROW_NUMBER () yang ditentukan.
redcalx
22
Satu-satunya cara untuk menjamin pesanan dalam SQL adalah dengan memintanya
Remus Rusanu
0

Sebenarnya pertanyaan (lama) dapat diperluas untuk juga menyertakan partisi dengan bagian, karena tampaknya ada urutan implisit dengan pertama partisi oleh dan kemudian urutan oleh bagian (s)

Jadi tidak sesederhana yang disarankan beberapa orang untuk menetapkan row_number dan menggunakannya untuk memesan.

Kita akan membutuhkan sql bersarang yang mengekstraksi partisi dengan klausa juga (jika kita tidak ingin hanya mengulanginya saja)

Secara empiris kita tampaknya mendapatkan baris terakhir dari pemesanan secara implisit

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

Tetapi yang kita kekurangan adalah bukti atau jaminan yang selalu ada.

(Jika ada beberapa panggilan Row_Number () yang dimainkan, itu adalah TERAKHIR yang tampaknya memberikan pemesanan)

JUGA CATATAN jika Anda secara eksplisit menambahkan pesanan dengan rencana eksekusi dengan jelas menunjukkan langkah-sortir akhir, dan mengurutkan set yang sudah diurutkan adalah jenis-kasus terburuk, maka dibutuhkan secara substansial lebih lama dengan Order By daripada tanpa

Eske Rahn
sumber
1
Ini tidak benar-benar menjawab pertanyaan, dan tampaknya tidak setuju dengan jawaban yang diterima, dan jawaban yang sangat terangkat.
Erik Darling
Saya setuju bahwa komentar saya lebih dari sekadar jawaban. Jawaban yang diterima sebenarnya bukan jawaban, kecuali dikatakan bahwa kita sebaiknya tidak memercayai urutannya - dan memang itulah pertanyaannya. Hal ini dapat dilihat oleh rencana eksekusi yang benar-benar melakukan pengurutan, dan jika kita menambahkan urutan eksplisit, kita mendapatkan pengurutan kedua. Tapi itu BUKAN bukti, itu hanya bagian dari pengetahuan empiris
Eske Rahn
(Tentu saja ini hanya akan berhasil jika tidak ada indeks yang cocok yang dapat digunakan untuk mengakses tabel, tetapi hanya menambahkannya untuk menunjukkan bahwa umumnya tidak bebas biaya untuk memberikan pesanan secara eksplisit)
Eske Rahn