Mengapa ORDER BY tidak termasuk dalam Tampilan?

51

Saya mengerti bahwa Anda tidak dapat memiliki ORDER BY pandangan. (Setidaknya dalam SQL Server 2012 saya bekerja dengan)

Saya juga mengerti bahwa cara "benar" untuk menyortir tampilan adalah dengan meletakkan ORDER BYsekitar SELECTpernyataan yang meminta tampilan.

Tetapi karena relatif baru untuk SQL praktis dan penggunaan pandangan, saya ingin memahami mengapa ini dilakukan dengan desain. Jika saya telah mengikuti sejarah dengan benar, ini pernah mungkin dan secara eksplisit dihapus dari SQL Server 2008 dan seterusnya (jangan mengutip saya pada versi yang tepat).

Namun, alasan terbaik yang dapat saya kemukakan mengapa Microsoft menghapus fitur ini adalah karena "sebuah tampilan adalah kumpulan data yang tidak disortir".

Saya berasumsi ada alasan logis yang bagus mengapa Tampilan harus tidak disortir. Mengapa tampilan tidak bisa hanya menjadi kumpulan data yang rata? Mengapa khusus tidak disortir? Tampaknya tidak sulit untuk menemukan situasi di mana (setidaknya bagi saya / IMHO) tampaknya sangat intuitif untuk memiliki tampilan yang diurutkan.

ngmiceli
sumber
2
Jawaban pertama sangat tepat. Saya sarankan jika Anda ingin memesan tampilan mengapa Anda tidak melakukan ini saja. Pilih [Kolom] Dari [YourView] Pesan Dengan [Kolom]
Zane
Jawaban singkat: "Karena alasan yang sama bahwa ORDER BY bukan milik tabel."
ypercubeᵀᴹ

Jawaban:

38

(Di samping pandangan yang diindeks, tentu saja.)

Tampilan tidak terwujud - data tidak disimpan, jadi bagaimana bisa diurutkan? Tampilan seperti prosedur tersimpan yang hanya berisi SELECTtanpa parameter ... itu tidak menyimpan data, itu hanya memegang definisi permintaan. Karena referensi yang berbeda untuk tampilan bisa memerlukan data yang diurutkan dengan cara yang berbeda, cara Anda melakukan ini - seperti memilih dari tabel, yang juga merupakan kumpulan baris yang tidak disortir, menurut definisi - adalah dengan memasukkan urutan pesanan pada kueri luar .

Juga untuk memberi sedikit wawasan tentang sejarah. Anda bisa tidak pernah dimasukkan ke ORDER BYdalam sebuah tampilan, tanpa juga termasuk TOP. Dan dalam hal ini ORDER BYbaris yang ditentukan dimasukkan TOP, bukan bagaimana mereka akan disajikan. Itu hanya kebetulan bahwa dalam SQL Server 2000, jika TOPitu 100 PERCENTatau {some number >= number of rows in the table}, optimizer cukup sederhana dan akhirnya menghasilkan sebuah rencana dengan semacam yang cocok dengan TOP/ORDER BY. Tapi perilaku ini tidak pernah dijamin atau didokumentasikan - itu hanya didasarkan pada pengamatan, yang merupakan kebiasaan buruk . Ketika SQL Server 2005 keluar, perilaku ini mulai "melanggar" karena perubahan dalam pengoptimal yang menyebabkan berbagai rencana dan operator yang digunakan - antara lain,TOP / ORDER BYakan diabaikan sepenuhnya jika itu TOP 100 PERCENT. Beberapa pelanggan mengeluhkan hal ini dengan sangat keras sehingga Microsoft mengeluarkan tanda bendera untuk mengembalikan perilaku lama. Saya tidak akan memberi tahu Anda apa benderanya karena saya tidak ingin Anda menggunakannya dan saya ingin memastikan bahwa maksudnya benar - jika Anda ingin urutan pengurutan yang dapat diprediksi, gunakan ORDER BYpada permintaan luar.

Untuk meringkas dan hanya untuk memperjelas poin yang Anda buat: Microsoft tidak menghapus apa pun. Mereka membuat produk lebih baik, dan sebagai efek samping dari perilaku yang tidak berdokumen dan tidak dijamin ini menjadi kurang dapat diandalkan. Secara keseluruhan, saya pikir produknya lebih baik.

Aaron Bertrand
sumber
Di sini disebutkan (dalam komentar) bahwa TOPmelakukan operasi kursor atas hasil yang ditetapkan. Untuk itu dapat memiliki perintah eksplisit.
Tim Schmelter
@TimSchmelter yang tidak membantu ketika pengoptimal melihat TOP 100 PERCENT / ORDER BYdan menghapusnya dari paket sepenuhnya. Cobalah.
Aaron Bertrand
Itu hanya sidenote. Sisa dari komentar adalah sebagai berikut: "SELECT TOP x trick dijadwalkan akan ditinggalkan dalam versi SQL Server yang akan datang, jadi akan lebih baik untuk tidak menggunakannya sama sekali."
Tim Schmelter
@TimSchmelter sudah no-op. Saya tidak berpikir itu akan berhenti berfungsi dalam versi baru dalam waktu dekat, karena akan merusak terlalu banyak kode yang ada.
Aaron Bertrand
2
@TimSchmelter ada pesanan tidak berbicara tentang urutan baris, itu berbicara tentang urutan kolom dalam satu baris. Dalam SQL Server kita umumnya tidak berbicara tentang baris menjadi tupel karena implementasi fisik dari suatu baris sangat jelas bagi kami (tabel mencantumkan kolom dalam urutan yang Anda tetapkan).
Aaron Bertrand
9

Jika tampilan dibiarkan disortir, lalu apa urutan hasil di sini?

CREATE VIEW dbo.V1
AS
  SELECT number
  FROM   SomeTable
  ORDER  BY number ASC

GO

CREATE VIEW dbo.V2
AS
  SELECT number
  FROM   SomeTable
  ORDER  BY number DESC

GO

SELECT *
FROM   dbo.V1
       JOIN dbo.V2
         ON V1.number = V2.number 
Martin Smith
sumber
Saya tidak mengerti poin ini. Alih-alih menulis tampilan basis data, Anda dapat menulis kueri sql normal. Jadi apa yang harus menjadi urutan hasil dalam kasus itu? terima kasih
hqt
7

satu kemungkinan adalah untuk menghindari jenis yang bertentangan - jika tampilan disortir berdasarkan satu urutan dan pilih pada tampilan yang disortir oleh urutan lain (tidak menyadari jenis tampilan), mungkin ada kinerja yang memukul. Jadi lebih aman untuk meninggalkan persyaratan penyortiran kepada pengguna.

alasan lain, sortir datang dengan biaya kinerja, jadi mengapa menghukum semua pengguna tampilan, ketika hanya beberapa pengguna yang membutuhkan sortir itu ..

srini.venigalla
sumber
5

ANSI SQL hanya memungkinkan ORDER BYkueri terluar untuk berbagai alasan, salah satunya adalah apa yang terjadi ketika subselect / view / CTE digabungkan ke tabel lain dan kueri luar memiliki ORDER BYitu sendiri.

SQL server tidak pernah mendukungnya dalam tampilan (kecuali jika Anda menipu menggunakan TOP 100 PERCENTyang menurut saya sebagian besar memicu bug).

Bahkan jika Anda memicu bug, hasilnya tidak pernah dapat diandalkan, dan penyortiran tidak selalu sesuai dengan yang Anda harapkan.

Lihat posting blog ini oleh tim Pengoptimal Permintaan untuk penjelasan teknis lengkap TOP 100 Persen ORDER OLEH Dianggap Berbahaya.

Implementasi paket default untuk kode ini terjadi untuk mengurutkan baris sebagai bagian dari melakukan operasi TOP. Seringkali ini berarti bahwa hasilnya kebetulan dikembalikan dalam urutan yang diurutkan, dan ini membuat pelanggan percaya bahwa ada jaminan bahwa baris diurutkan. Ini sebenarnya tidak demikian. Jika Anda ingin baris dikembalikan ke pengguna dalam urutan yang disortir, Anda perlu menggunakan ORDER OLEH pada blok permintaan terluar (per ANSI) untuk menjamin urutan presentasi output.

Tom V
sumber
3

Tampilan berperilaku seperti tabel yang isinya ditentukan oleh hasil kueri.

Tabel tidak memiliki pesanan; mereka hanya sekumpulan baris.

Oleh karena itu, pandangan tidak memiliki urutan. Anda dapat mengurutkannya dengan memilih baris dalam ORDER tertentu.

duskwuff
sumber
1
Tabel ... hanya tas baris - dan kemudian viwes hanya maya kantong maya baris - dilihat "tidak ada" - misalnya tidak ada data yang disimpan bagi mereka sama sekali - mereka hanya "definisi disimpan dari query untuk dieksekusi ", pada dasarnya.
marc_s
1
+1 Setara dengan tabel dan tampilan bagi saya alasan utama mengapa tampilan tidak boleh mengandung "pesanan oleh"
miracle173
1
"Tampilan berperilaku seperti tabel" . Saya akan mengatakan bahwa "Tampilan berperilaku seperti tabel dasar. Tampilan adalah tabel."
ypercubeᵀᴹ
-2

Satu jawaban yang belum diberikan adalah bahwa "pesanan oleh" dapat mengganggu pendorong predikat yang dapat sangat mempengaruhi kinerja.

Contohnya adalah memiliki tampilan yang menggulung set besar data ke dalam ringkasan 10 baris yang berada di atas 10 / Dipesan:

select * from TopOrderedView; -- Ordered 10 line summary in 5s

Untuk kasus yang sama dengan predikat kuat:

select * from TopOrderedView where <condition>; -- Ordered 2 line summary in still 5s

Masih membutuhkan jumlah waktu yang sama karena top / order dengan memblokir predikat dari dijalankan sebelumnya dalam pipa. Ini dapat menyebabkan baris yang tidak dibutuhkan diproses dan rencananya akan serupa dengan yang tanpa predikat.

Apakah dorongan harus terjadi sebelum pesanan oleh benar-benar pilihan pengembang dan dapat mengubah jawabannya. Paling sering dorongan adalah niat logis.

Menggunakan "top 100 persen" secara logis memungkinkan pendorong mendorong namun implementasi sayangnya mengabaikan "pesanan oleh" untuk kasus ini dan mengalahkan tujuannya.

Untuk kasus penggunaan nyata, kompromi yang bagus akan membuat mesin melakukan "pesanan dengan menarik." Ini akan memungkinkan "pesanan oleh" ditentukan dalam tampilan (dengan 100 persen teratas atau tanpa puncak) dan pesanan itu hanya digunakan jika tampilan dipilih secara langsung, tanpa urutan eksplisit oleh, tanpa gabungan, tanpa agregat, tanpa lihat rantai dll. Kedua kasus yang tercantum di atas dapat didukung oleh model sederhana ini.

crokusek
sumber
-6

Anda dapat membuat tampilan yang telah dipesan oleh dan mempertahankan pesanan saat ditanya setelah:

pilih top 99,99999999999999 persen * dari ..... dipesan oleh

NasF1
sumber
1
Kenapa tidak adil SELECT TOP 100 PERCENT ...?
Max Vernon
2
@ Max mungkin mirip dengan trik ini - itu tidak membuatnya menjadi ide yang bagus.
Aaron Bertrand
Setuju, @AaronBertrand - hanya mencatat tidak perlu menggunakan 99,99999999999 :-)
Max Vernon