Saya punya tabel yang berpotensi menyimpan ratusan ribu bilangan bulat
desc id_key_table;
+----------------+--------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+----------------+--------------+------+-----+---------+-------+
| id_key | int(16) | NO | PRI | NULL | |
+----------------+--------------+------+-----+---------+-------+
Dari suatu program, saya memiliki satu set bilangan bulat besar. Saya ingin melihat bilangan bulat mana yang TIDAK dalam kolom id_key di atas.
Sejauh ini saya telah datang dengan pendekatan berikut:
1) Ulangi setiap integer dan lakukan:
select count(*) count from id_key_table where id_key = :id_key
Saat hitung 0, id_key tidak ada di tabel.
Ini sepertinya cara yang mengerikan dan mengerikan untuk melakukannya.
2) Buat tabel sementara, masukkan masing-masing nilai ke dalam tabel sementara, dan lakukan JOIN pada dua tabel.
create temporary table id_key_table_temp (id_key int(16) primary key );
insert into id_key_table_temp values (1),(2),(3),...,(500),(501);
select temp.id_key
from id_key_table_temp temp left join id_key_table as main
on temp.id_key = main.id_key
where main.killID is null;
drop table id_key_table_temp;
Ini sepertinya pendekatan terbaik, namun, saya yakin ada pendekatan yang jauh lebih baik yang belum saya pikirkan. Saya lebih suka tidak harus membuat tabel sementara dan menggunakan satu permintaan untuk menentukan bilangan bulat mana yang hilang.
Apakah ada permintaan yang tepat untuk jenis pencarian ini?
(MySQL)
Jawaban:
Solusi kedua Anda menggunakan LEFT JOIN sejauh ini merupakan pendekatan terbaik. Saya tidak akan menggunakan tabel sementara, saya akan menggunakan tabel biasa dan mengisinya dengan nilai-nilai baru setiap kali Anda ingin menjalankan kueri.
sumber
Kedengarannya seperti "set besar bilangan bulat" masih jauh lebih kecil dari tabel dengan "ratusan ribu bilangan bulat". Dengan anggapan itu dan kecuali ada cara di MySQL untuk menggunakan array bilangan bulat Anda sebagai tabel dalam pernyataan SQL Anda, opsi kedua Anda mungkin yang terbaik. Ini harus melakukan pemindaian penuh dari tabel temp dan indeks pada tabel utama. Manfaat utama adalah hanya memindai indeks yang berisi ratusan ribu bilangan bulat satu kali dan hanya mengirim hasil kepada klien. Permintaan Anda dapat (tetapi tidak perlu) ditulis ulang sebagai berikut:
sumber
Alih-alih tabel sementara dan menyisipkan dengan
insert into id_key_table_temp values (1),(2),(3),...,(500),(501);
, Anda bisa membuat subquery dengan semua nilai yang Anda coba periksa:sumber
Seperti disebutkan dalam komentar saya, ini mungkin lebih cocok untuk stackoverflow. Namun, saya pikir kedua solusi itu bukan yang terbaik:
Solusi 1 membutuhkan beberapa panggilan pilih, sangat tidak efisien
Solusi 2 lebih baik, tetapi saya tidak yakin biaya memasukkan banyak nilai adalah solusi terbaik.
Kemungkinan solusi 3 adalah membuat satu permintaan:
dan secara terprogram mendapatkan perbedaan dari set integer Anda dan apa yang ada di DB. Paling buruk, (karena banyak bilangan bulat) Rute ini harus lebih baik daripada Solusi 1. Solusi 2 berpotensi juga mengembalikan banyak bilangan bulat (jika tabel memiliki banyak bilangan yang tidak ada dalam dataset Anda), sehingga tergantung ™!
sumber
Saya cukup banyak membahas ini di StackOverflow , tapi saya ingin menguraikan lebih lanjut tentang penggunaan tabel temp permanen (PermTemp). ( temp permanen, bukankah itu oxymoron ?)
Di StackOverflow , saya memiliki tes prosedur tersimpan. BuatSampleTable dan test.GetMissingIntegers membuat tabel sampel dan kemudian membuat tabel temp dinamis untuk diisi sebelum melakukan JOIN besar untuk menemukan perbedaan.
Kali ini, mari kita buat tabel sampel bersama dengan tabel tabel permanen.
Inilah test.LoadSampleTables:
Setelah menjalankan ini, berikut adalah tabel dan isinya:
Berikut adalah Pemicu untuk tabel PermTemp
Sekarang, mari kita mengimpor kumpulan catatan baru, table test.weekly_batch, beberapa kunci yang digunakan sebelumnya, kunci-kunci lain yang dipukul dengan merek baru:
Mari kita ikuti test.weekly_batch dan dengan aman menggabungkannya ke test.id_key_table_keys dan membentuk tabel test.new_keys_to_load:
Inilah hasilnya:
Dari titik ini, cukup gunakan tabel new_keys_to_load sebagai daftar merek memukul kunci baru untuk diimpor. Karena new_keys_to_load lebih kecil dari tabel PermTemp, Anda harus selalu menggunakan new_keys_to_load di sebelah kiri LEFT JOIN.
sumber