Apakah ada cara yang bagus di MySQL untuk mereplikasi fungsi SQL Server ROW_NUMBER()
?
Sebagai contoh:
SELECT
col1, col2,
ROW_NUMBER() OVER (PARTITION BY col1, col2 ORDER BY col3 DESC) AS intRow
FROM Table1
Lalu saya bisa, misalnya, menambahkan syarat untuk membatasi intRow
ke 1 untuk mendapatkan satu baris dengan tertinggi col3
untuk setiap (col1, col2)
pasangan.
greatest-n-per-group
untuk memandu Anda ke pertanyaan serupa.Sql-Server
Tag dihapus karena ini adalah item pilihan tertinggi pada pencarian tag gabungan tetapi tidak benar-benar relevan dengan SQL Server.Jawaban:
Itu maksimum groupwise , salah satu pertanyaan SQL yang paling sering ditanyakan (karena sepertinya itu harus mudah, tetapi sebenarnya itu jenis tidak).
Saya sering mengisi untuk null-self-join:
"Dapatkan baris dalam tabel yang tidak ada baris lain dengan pencocokan col1, col2 memiliki col3 yang lebih tinggi." (Anda akan melihat ini dan sebagian besar solusi maksimum groupwise lainnya akan mengembalikan beberapa baris jika lebih dari satu baris memiliki col1, col2, col3 yang sama. Jika itu masalah Anda mungkin perlu beberapa post-processing.)
sumber
SELECT t1.id FROM test t1 LEFT JOIN test t2 ON t1.id>t2.id WHERE t2.id IS NULL;
Apakah tidak memerlukann*n/2 + n/2
perbandingan IS NULL untuk menemukan baris tunggal? Apakah ada optimasi yang tidak saya lihat? Saya mencoba mengajukan pertanyaan serupa kepada Bill di utas lain tetapi dia tampaknya mengabaikannya.SELECT t0.col3 FROM table AS t0 WHERE NOT EXISTS (select 1 from table AS t1 ON t0.col1=t1.col1 AND t0.col2=t1.col2 AND t1.col3>t0.col3)
Tidak ada fungsi peringkat di MySQL. Yang paling dekat yang bisa Anda dapatkan adalah menggunakan variabel:
Iya. Jika itu adalah Oracle, Anda bisa menggunakan fungsi LEAD untuk memuncak pada nilai berikutnya. Untungnya, Quassnoi mencakup logika untuk apa yang perlu Anda terapkan di MySQL .
sumber
SELECT @row_num:=@row_num+1 AS row_number, t.id FROM (SELECT * FROM table1 WHERE col = 264 ORDER BY id) t, (SELECT @row_num:=0) var;
Saya selalu berakhir dengan pola ini. Diberikan tabel ini:
Anda bisa mendapatkan hasil ini:
Dengan menjalankan kueri ini, yang tidak memerlukan variabel apa pun yang ditentukan:
Semoga itu bisa membantu!
sumber
<
,>
,<=
,>=
pegangan CHAR dan VARCHAR jenis data pada urutan abjad; Saya berharap, persis apa yang Anda cari.row_numbers <= 2
Dan terima kasih besar untuk jawaban ini Mosty, sempurna!sumber
Lihat Artikel ini, ini menunjukkan cara meniru SQL ROW_NUMBER () dengan partisi oleh di MySQL. Saya mengalami skenario yang sama ini dalam Implementasi WordPress. Saya membutuhkan ROW_NUMBER () dan tidak ada di sana.
http://www.explodybits.com/2011/11/mysql-row-number/
Contoh dalam artikel ini menggunakan satu partisi per bidang. Untuk mempartisi dengan bidang tambahan Anda dapat melakukan sesuatu seperti ini:
Menggunakan concat_ws menangani null. Saya menguji ini terhadap 3 bidang menggunakan int, tanggal, dan varchar. Semoga ini membantu. Lihat artikel saat itu memecah permintaan ini dan menjelaskannya.
sumber
limit 18446744073709551615
ke memaksaorder by
klausa.concat_ws
dengan string kosong''
berbahaya:concat_ws('',12,3) = concat_ws('',1,23)
. Lebih baik menggunakan pemisah'_'
atau menggunakan solusi @Kenneth Xu.Dari
MySQL 8.0.0
dan di atas Anda dapat menggunakan fungsi windowed.1.4 Apa yang Baru di MySQL 8.0 :
ROW_NUMBER () over_clause :
Demo:
Demo DBFiddle
sumber
Saya juga akan memilih solusi Mosty Mostacho dengan sedikit modifikasi pada kode permintaannya:
Yang akan memberikan hasil yang sama:
untuk meja:
Dengan satu-satunya perbedaan bahwa kueri tidak menggunakan GABUNG dan KELOMPOK OLEH, mengandalkan bersarang pilih sebagai gantinya.
sumber
Saya akan mendefinisikan fungsi:
maka saya bisa melakukan:
Sekarang Anda tidak memiliki subquery, yang tidak dapat Anda lihat.
sumber
permintaan untuk row_number di mysql
sumber
Tidak ada funtion like
rownum
,row_num()
di MySQL tapi jalannya seperti di bawah ini:sumber
Solusi yang saya temukan untuk bekerja paling baik adalah menggunakan subquery seperti ini:
Kolom PARTITION BY baru saja dibandingkan dengan '=' dan dipisahkan oleh AND. Kolom ORDER BY akan dibandingkan dengan '<' atau '>', dan dipisahkan oleh OR.
Saya telah menemukan ini sangat fleksibel, bahkan jika itu sedikit mahal.
sumber
Fungsionalitas rownumber tidak dapat ditiru. Anda mungkin mendapatkan hasil yang Anda harapkan, tetapi kemungkinan besar Anda akan kecewa pada tahap tertentu. Inilah yang dikatakan dokumentasi mysql:
Salam, Georgi.
sumber
MariaDB 10.2 menerapkan "Fungsi Jendela", termasuk RANK (), ROW_NUMBER () dan beberapa hal lainnya:
https://mariadb.com/kb/en/mariadb/window-functions/
Berdasarkan ceramah di Percona Live bulan ini, mereka dioptimalkan dengan cukup baik.
Sintaksnya identik dengan kode dalam Pertanyaan.
sumber
Saya tidak melihat jawaban sederhana yang meliputi bagian "PARTISI DENGAN" jadi inilah milik saya:
Dalam contoh sederhana ini saya hanya menempatkan satu tetapi Anda dapat memiliki beberapa bagian "PARTISI DENGAN"
sumber
Sedikit terlambat tetapi juga dapat membantu seseorang yang mencari jawaban ...
Antara contoh baris / row_number - kueri rekursif yang dapat digunakan dalam SQL apa pun:
sumber
Ini memungkinkan fungsionalitas yang sama yang disediakan ROW_NUMBER () DAN PARTITION BY untuk dicapai di MySQL
sumber
Juga agak terlambat tetapi hari ini saya memiliki kebutuhan yang sama jadi saya melakukan pencarian di Google dan akhirnya pendekatan umum sederhana ditemukan di sini di artikel Pinal Dave http://blog.sqlauthority.com/2014/03/09/mysql-reset-row -nomor-untuk-setiap-grup-partisi-dengan-baris-nomor /
Saya ingin fokus pada pertanyaan awal Paul (itu adalah masalah saya juga) jadi saya merangkum solusi saya sebagai contoh kerja.
Karena kami ingin mempartisi lebih dari dua kolom, saya akan membuat variabel SET selama iterasi untuk mengidentifikasi jika grup baru dimulai.
Angka 3 berarti pada parameter pertama MAKE_SET yang saya inginkan kedua nilai dalam SET (3 = 1 | 2). Tentu saja jika kita tidak memiliki dua atau lebih kolom yang membangun grup, kita dapat menghilangkan operasi MAKE_SET. Konstruksinya persis sama. Ini bekerja untuk saya sesuai kebutuhan. Banyak terima kasih kepada Pinal Dave untuk demonstrasi yang jelas.
sumber
ORDER BY
dalam sebuah subquery dapat diabaikan (lihat mariadb.com/kb/en/mariadb/… ). Solusi yang disarankan untuk itu adalah menambahkanLIMIT 18446744073709551615
ke subquery, yang memaksa semacam. Namun ini dapat menyebabkan masalah kinerja dan tidak valid untuk tabel yang sangat besar :)Ini juga bisa menjadi solusi:
sumber
MySQL telah mendukung ROW_NUMBER () sejak versi 8.0+ .
Jika Anda menggunakan MySQL 8.0 atau lebih baru, periksa fungsi ROW_NUMBER (). Jika tidak, Anda harus mengemulasi fungsi ROW_NUMBER ().
Row_number () adalah fungsi peringkat yang mengembalikan nomor urut baris, mulai dari 1 untuk baris pertama.
untuk versi yang lebih lama,
sumber
Penting: Harap pertimbangkan untuk memutakhirkan ke MySQL 8+ dan gunakan fungsi ROW_NUMBER () yang didefinisikan dan didokumentasikan, dan parit peretasan lama yang dikaitkan dengan fitur versi MySQL kuno yang terbatas fitur
Sekarang inilah salah satu dari peretasan itu:
Jawaban di sini yang sebagian besar / semua variabel in-query tampaknya mengabaikan fakta bahwa dokumentasi mengatakan (parafrase):
Dengan demikian, ada risiko mereka akan mengeluarkan jawaban yang salah, karena mereka biasanya melakukan a
Jika ini pernah dievaluasi dari bawah ke atas, nomor baris akan berhenti berfungsi (tidak ada partisi)
Jadi kita perlu menggunakan sesuatu dengan urutan eksekusi yang terjamin. Masukkan KASUS KAPAN:
Sebagai garis besar ld, urutan penugasan prevcol adalah penting - prevcol harus dibandingkan dengan nilai baris saat ini sebelum kami menetapkan nilai dari baris saat ini (jika tidak itu akan menjadi nilai baris baris saat ini, bukan nilai baris baris sebelumnya) .
Inilah cara ini cocok:
KAPAN pertama dievaluasi. Jika col baris ini sama dengan col baris sebelumnya maka @r bertambah dan dikembalikan dari KASUS. Nilai yang dikembalikan ini disimpan dalam @r. Ini adalah fitur MySQL yang tugasnya mengembalikan nilai baru dari apa yang ditugaskan ke @r ke dalam baris hasil.
Untuk baris pertama pada set hasil, @prevcol adalah nol (ini diinisialisasi ke nol dalam subquery) sehingga predikat ini salah. Predikat pertama ini juga mengembalikan false setiap kali perubahan col (baris saat ini berbeda dengan baris sebelumnya). Ini menyebabkan WHEN kedua dievaluasi.
Predikat WHEN kedua selalu salah, dan itu ada murni untuk menetapkan nilai baru ke @prevcol. Karena col baris ini berbeda dengan col baris sebelumnya (kita tahu ini karena jika itu sama, WHEN pertama akan digunakan), kita harus menetapkan nilai baru untuk menyimpannya untuk pengujian di waktu berikutnya. Karena tugas dibuat dan kemudian hasil tugas dibandingkan dengan nol, dan apa pun yang disamakan dengan nol salah, predikat ini selalu salah. Tetapi setidaknya mengevaluasi itu melakukan tugasnya menjaga nilai col dari baris ini, sehingga dapat dievaluasi terhadap nilai col baris berikutnya
Karena WHEN kedua salah, itu berarti dalam situasi di mana kolom kita dipartisi oleh (col) telah berubah, itu adalah ELSE yang memberikan nilai baru untuk @r, memulai kembali penomoran dari 1
Kita ini sampai pada situasi di mana ini:
Memiliki bentuk umum:
Catatan kaki:
P dalam pcol berarti "partisi", o dalam ocol berarti "urutan" - dalam bentuk umum saya menjatuhkan "prev" dari nama variabel untuk mengurangi kekacauan visual
Kurung di sekitar
(@pcolX := colX) = null
itu penting. Tanpa mereka Anda akan menetapkan nol untuk @pcolX dan semuanya berhenti berfungsiIni kompromi bahwa set hasil harus dipesan oleh kolom partisi juga, untuk kolom sebelumnya dibandingkan untuk bekerja. Dengan demikian, Anda tidak dapat memesan nomor yang Anda tentukan sesuai dengan satu kolom, tetapi hasil yang Anda tentukan dipesan ke yang lain. Anda mungkin dapat menyelesaikan ini dengan subkueri tapi saya percaya dokumen tersebut juga menyatakan bahwa pemesanan subkueri dapat diabaikan kecuali LIMIT digunakan dan ini dapat berdampak kinerja
Saya belum menyelidiki lebih jauh dari pengujian bahwa metode ini bekerja, tetapi jika ada risiko bahwa predikat di SAAT kedua akan dioptimalkan jauh (apa pun dibandingkan dengan nol adalah nol / salah jadi mengapa repot-repot menjalankan tugas) dan tidak dieksekusi , itu juga berhenti. Ini sepertinya tidak terjadi dalam pengalaman saya, tetapi saya akan dengan senang hati menerima komentar dan mengusulkan solusi jika itu bisa terjadi
Mungkin bijaksana untuk memberikan nulls yang membuat @pcolX ke tipe kolom Anda yang sebenarnya, dalam subquery yang membuat variabel @pcolX, yaitu:
select @pcol1 := CAST(null as INT), @pcol2 := CAST(null as DATE)
sumber
Ini bukan solusi yang paling kuat - tetapi jika Anda hanya ingin membuat peringkat dipartisi pada bidang dengan hanya beberapa nilai yang berbeda, mungkin tidak akan sulit untuk menggunakan beberapa kasus ketika logika dengan variabel sebanyak yang Anda butuhkan.
Sesuatu seperti ini telah bekerja untuk saya di masa lalu:
Harapan itu masuk akal / membantu!
sumber
Ini Bekerja dengan sempurna bagi saya untuk membuat RowNumber ketika kami memiliki lebih dari satu kolom. Dalam hal ini dua kolom.
sumber
sumber
sumber