Saya ingin menemukan "celah" pertama di kolom penghitung dalam tabel SQL. Misalnya, jika ada nilai 1,2,4 dan 5, saya ingin mencari 3.
Saya tentu saja bisa mendapatkan nilai secara berurutan dan melihatnya secara manual, tetapi saya ingin tahu apakah ada cara untuk melakukannya di SQL.
Selain itu, itu harus SQL yang cukup standar, bekerja dengan DBMS yang berbeda.
sql
gaps-and-islands
Touko
sumber
sumber
LAG(id, 1, null)
fungsi denganOVER (ORDER BY id)
klausa.Jawaban:
Dalam
MySQL
danPostgreSQL
:Masuk
SQL Server
:Masuk
Oracle
:ANSI
(bekerja di mana saja, paling tidak efisien):Sistem yang mendukung fungsi jendela geser:
sumber
URL
juga, meskipun saya kira mungkin kode QR itu.[1, 2, 11, 12]
, maka ini hanya akan menemukan3
. Yang ingin saya temukan adalah 3-10 sebagai gantinya - pada dasarnya awal dan akhir dari setiap celah. Saya mengerti bahwa saya mungkin harus menulis skrip python saya sendiri yang memanfaatkan SQL (dalam kasus saya MySql), tetapi alangkah baiknya jika SQL dapat membuat saya lebih dekat dengan apa yang saya inginkan (saya memiliki tabel dengan 2 juta baris yang memiliki celah, jadi saya perlu mengirisnya menjadi potongan-potongan kecil dan menjalankan beberapa SQL di atasnya). Saya kira saya bisa menjalankan satu kueri untuk menemukan awal celah, lalu kueri lain untuk menemukan akhir celah, dan mereka "menggabungkan" dua urutan.NULL
, tidak0
, jika tabel kosong. Ini berlaku untuk semua database.Jawaban Anda semuanya berfungsi dengan baik jika Anda memiliki nilai pertama id = 1, jika tidak, celah ini tidak akan terdeteksi. Misalnya jika nilai id tabel Anda adalah 3,4,5, kueri Anda akan menghasilkan 6.
Saya melakukan sesuatu seperti ini
sumber
Sebenarnya tidak ada cara SQL yang sangat standar untuk melakukan ini, tetapi dengan beberapa bentuk klausa pembatas yang dapat Anda lakukan
(MySQL, PostgreSQL)
atau
(SQL Server)
atau
(Peramal)
sumber
Hal pertama yang terlintas di kepalaku. Tidak yakin apakah itu ide yang baik untuk pergi dengan cara ini sama sekali, tetapi harus berhasil. Misalkan tabelnya
t
dan kolomnya adalahc
:Sunting: Yang ini mungkin lebih cepat (dan lebih pendek!):
sumber
LEFT OUTER JOING t2
akan meminta Anda untuk memilikit2
tabel, yang hanya sebuah alias.Ini berfungsi di SQL Server - tidak dapat mengujinya di sistem lain tetapi tampaknya standar ...
Anda juga bisa menambahkan titik awal ke klausa where ...
Jadi jika Anda memiliki 2000, 2001, 2002, dan 2005 di mana 2003 dan 2004 tidak ada, itu akan mengembalikan 2003.
sumber
Solusi berikut ini:
Menomori baris yang diurutkan secara berurutan dalam klausa " dengan " dan kemudian menggunakan kembali hasilnya dua kali dengan gabungan dalam pada nomor baris, tetapi diimbangi dengan 1 untuk membandingkan baris sebelumnya dengan baris setelahnya, mencari ID dengan celah lebih besar dari 1. Lebih dari yang diminta tetapi lebih dapat diterapkan secara luas.
Kueri dalam menghasilkan:
Kueri luar menghasilkan:
sumber
Inner bergabung ke tampilan atau urutan yang memiliki semua kemungkinan nilai.
Tidak ada meja? Buatlah meja. Saya selalu menyimpan meja boneka hanya untuk ini.
Kemudian,
sumber
Untuk
PostgreSQL
Contoh yang memanfaatkan kueri rekursif.
Ini mungkin berguna jika Anda ingin menemukan celah dalam rentang tertentu (ini akan berfungsi bahkan jika tabel kosong, sedangkan contoh lainnya tidak)
sumber
Tebakanku:
sumber
Yang ini menjelaskan semua yang disebutkan sejauh ini. Ini mencakup 0 sebagai titik awal, yang akan menjadi default jika tidak ada nilai juga. Saya juga menambahkan lokasi yang sesuai untuk bagian lain dari kunci multi-nilai. Ini hanya diuji di SQL Server.
sumber
Saya menulis cara cepat untuk melakukannya. Tidak yakin ini yang paling efisien, tetapi menyelesaikan pekerjaan. Perhatikan bahwa ini tidak memberi tahu Anda celahnya, tetapi memberi tahu Anda id sebelum dan sesudah celah (perlu diingat bahwa celah itu bisa berupa beberapa nilai, jadi misalnya 1,2,4,7,11 dll)
Saya menggunakan sqlite sebagai contoh
Jika ini adalah struktur tabel Anda
dan ini adalah baris Anda
Pertanyaannya adalah
https://gist.github.com/wkimeria/7787ffe84d1c54216f1b320996b17b7e
sumber
sumber
Berikut adalah solusi SQL standar yang berjalan di semua server database tanpa perubahan:
Lihat beraksi untuk;
sumber
Ini berfungsi untuk tabel kosong atau dengan nilai negatif juga. Baru saja diuji di SQL Server 2012
sumber
Jika Anda menggunakan Firebird 3, ini yang paling elegan dan sederhana:
sumber
sumber
Menemukan sebagian besar pendekatan berjalan sangat, sangat lambat
Saya berasumsi bahwa urutan dimulai dari `1`.mysql
. Inilah solusi saya untukmysql < 8.0
. Diuji pada catatan 1 juta dengan jeda mendekati akhir ~ 1 detik hingga selesai. Tidak yakin apakah itu cocok dengan citarasa SQL lainnya.sumber
Jika penghitung Anda mulai dari 1 dan Anda ingin menghasilkan urutan nomor pertama (1) saat kosong, berikut adalah bagian kode yang dikoreksi dari jawaban pertama yang valid untuk Oracle:
sumber
sumber
Jika angka-angka di kolom adalah bilangan bulat positif (dimulai dari 1) maka berikut adalah cara menyelesaikannya dengan mudah. (dengan asumsi ID adalah nama kolom Anda)
sumber