Implementasi Basis Data ORDER OLEH dalam Subquery

10

Saya menggunakan aplikasi (MapServer - http://mapserver.org/ ) yang membungkus pernyataan SQL, sehingga pernyataan ORDER BY berada dalam permintaan dalam. Misalnya

SELECT * FROM (
        SELECT ID, GEOM, Name
        FROM t
        ORDER BY Name
        ) as tbl

Aplikasi ini memiliki banyak driver basis data yang berbeda. Saya terutama menggunakan driver MS SQL Server, dan SQL Server 2008. Ini melempar kesalahan jika ORDER BY ditemukan dalam subquery.

Dari MS Documents (meskipun ini untuk SQL Server 2000 sepertinya masih berlaku):

Saat Anda menggunakan klausa ORDER BY dalam tampilan, fungsi inline, tabel turunan, atau subquery, itu tidak menjamin output yang dipesan. Sebagai gantinya, klausa ORDER BY hanya digunakan untuk menjamin bahwa set hasil yang dihasilkan oleh operator Top memiliki susunan yang konsisten. Klausa ORDER BY hanya menjamin hasil yang dipesan ditetapkan ketika ditentukan dalam pernyataan SELECT terluar.

Namun jenis kueri yang sama ketika dijalankan di Postgres (9) dan Oracle mengembalikan hasil - dengan urutan seperti yang didefinisikan dalam subquery. Dalam Postgres, rencana kueri menunjukkan hasilnya diurutkan dan catatan rilis Postgres menyertakan item yang menyiratkan pesanan subquery digunakan:

Hindari pengurutan saat subquery ORDER BY cocok dengan kueri atas

http://en.wikipedia.org/wiki/Order_by menyatakan:

Meskipun beberapa sistem basis data mengizinkan spesifikasi klausa ORDER BY dalam subselect atau melihat definisi, keberadaannya tidak berpengaruh.

Namun dari pengecekan saya sendiri dari rencana permintaan:

  • SQL Server 2008 tidak mendukung ORDER OLEH dalam subquery
  • Postgres 9 mendukung ORDER BY dalam subquery
  • Oracle 10g mendukung ORDER BY dalam subquery

Jadi pertanyaan saya apakah ada tautan yang secara resmi dapat mengkonfirmasi atau menyangkal bahwa Postgres dan Oracle tidak mengizinkan pengurutan dalam subquery?

geografi
sumber
2
Hanya karena Anda mengamati hasil-hasil tertentu tidak membuat mereka dijamin. Jika Anda ingin konsistensi, letakkan urutan di luar. Titik.
Aaron Bertrand
Idealnya ini yang akan diterapkan. Namun untuk sampai ke tahap ini akan melibatkan perubahan pada logika inti dan banyak driver database. Karena masalah ini belum pernah dilaporkan selama bertahun-tahun, sepertinya beberapa dbs secara konsisten mengimplementasikan ORDER BY dalam subqueries. Akan menyenangkan untuk mengetahui yang mana jika memungkinkan.
geografi
2
@geographika Bahkan jika beberapa DBMS melakukannya secara konsisten sampai sekarang, tidak ada jaminan mereka akan terus melakukan hal yang sama di masa depan. Sebagai contoh, peningkatan MySQL dari optimizer di 5.6 (dan MariaDB 5.3) akan mengidentifikasi ORDER BYsubquery sebagai berlebihan dan tidak melakukan penyortiran yang tidak perlu.
ypercubeᵀᴹ

Jawaban:

15

Anda harus membuat aplikasi Anda tidak menempatkan bagian ORDER BYdalam subquery (mungkin memiliki opsi untuk tidak menggunakan subquery yang tidak perlu di tempat pertama). Seperti yang sudah Anda temukan, sintaks ini tidak didukung di SQL Server tanpa TOP. Dan dengan TOP, kecuali Anda ingin mengabaikan beberapa baris, menggunakan TOP 100 PERCENTakan membuat yang ORDER BYdioptimalkan tetap pergi.

Dan di Oracle dan PostGres, hanya karena sintaks yang didukung , tidak berarti itu dipatuhi. Dan hanya karena Anda mengamatinya sebagai ditaati dalam beberapa skenario, tidak berarti itu akan terus dipatuhi saat versi baru keluar atau dengan perubahan halus pada data Anda, statistik, kueri itu sendiri, atau lingkungan.

Saya dapat meyakinkan Anda bahwa, tanpa keraguan , jika Anda ingin jaminan tentang pesanan, Anda harus memasukkan ORDER BYpermintaan yang paling luar. Ini harus menjadi doktrin yang Anda pegang erat-erat, apa pun platform yang Anda gunakan.

Anda meminta tautan yang secara resmi menyatakan bahwa ada sesuatu yang tidak didukung. Ini seperti melihat di manual pemilik mobil Anda untuk pernyataan resmi bahwa mobil Anda tidak bisa terbang.

Aaron Bertrand
sumber
Terima kasih. Saya pikir MSSQL memiliki pendekatan yang tepat dalam melempar kesalahan. Baik mendukung dan menerapkan penyortiran pada pertanyaan dalam, ketika bertentangan dengan prinsip SQL inti, tampaknya resep untuk bencana. Tidak yakin tentang analogi mobil - Anda perlu menambahkan mencarinya di manual saat mobil benar-benar terbang ..
geografi
-1

Saya akui ini busuk tetapi jika Anda dalam keadaan darurat coba kembalikan jumlah baris teratas dalam subquery. Mengembalikan 100 persen teratas tidak berfungsi tetapi jika Anda ingin mengatasi masalah, Anda dapat meminta jumlah baris dan meneruskannya ke TOP sebagai variabel. Saya menguji ini pada set database ke tingkat kompatibilitas 80 jadi saya pikir ini harus bekerja dengan SQL 2000.

SELECT * FROM (
        SELECT TOP (100000) ID, GEOM, Name
        FROM t
        ORDER BY Name
        ) as tbl
DBNull
sumber
Saya memang mencoba ini awalnya dan sepertinya baik untuk dataset kecil. Namun ketika saya mendapatkan recordset yang sangat besar penyortiran menjadi acak lagi di SQL Server 2008R2. Mungkin terkait dengan ukuran memori / halaman?
geografi
Maaf itu tidak membantu. Memilih 100 persen teratas juga menyebabkan penyortiran kembali ke acak.
DBNull
Ini tidak akan berfungsi jika kueri berjalan paralel, terutama jika Nametidak unik. Ini mungkin tidak terus bekerja secara seri jika optimizer memilih indeks yang berbeda, dengan urutan kolom kunci yang berbeda.
Erik Darling