MySQL - Cara memeriksa nilai di semua kolom

11

Saya ingin tahu, apakah ada cara yang baik untuk mencari semua kolom untuk nilai yang diberikan? Untuk tujuan saya, itu tidak perlu sama sekali cepat, itu hanya 1-off, dan saya benar-benar tidak ingin harus mengetikkan setiap nama bidang. Itulah tepatnya yang akan saya lakukan untuk saat ini, tetapi saya pikir pasti ada cara yang lebih baik.

Saya ingin mengubah ini:

SELECT * FROM table WHERE col1 = 'val' OR col2 = 'val' OR col3 = 'val';

dalam hal ini:

SELECT * FROM table WHERE * = 'val'

... atau, bahkan lebih baik (meskipun saya sangat meragukannya ...)

SELECT * FROM table WHERE * like '%val%'

Saya menemukan ini , yang sepertinya agak tidak terlalu dekat, tapi saya tidak menemukan yang lebih dekat:

SELECT whatever WHERE col1,col2 IN ((val1, val2), (val1, val2), ...)

Perbedaannya adalah, yang mencari pilihan kolom untuk nilai yang ditentukan, sedangkan saya mencoba mencari SEMUA kolom untuk nilai tunggal.

Itu tidak penting, seperti saya katakan lebih dari apa pun yang saya hanya ingin tahu

donutguy640
sumber

Jawaban:

23

SQL tidak menyediakan cara yang baik untuk melakukan ini karena mungkin bukan desain tabel yang baik untuk memiliki N kolom yang mungkin memiliki nilai di domain yang sama. Hal ini berpotensi kasus "kelompok mengulangi" seperti jika Anda memiliki kolom phone1, phone2, phone3, ... phoneN.

Jika Anda memiliki sejumlah kolom yang memiliki domain nilai logika yang sama, bisa jadi ini merupakan atribut multi-nilai (seperti contoh ponsel). Cara standar untuk menyimpan atribut multi-nilai adalah sebagai beberapa baris di tabel lain, dengan referensi ke baris milik mereka di tabel utama.

Jika Anda melakukannya, maka Anda hanya perlu mencari nilai tertentu dalam satu kolom dari tabel dependen.

SELECT t.* FROM mytable AS t
JOIN phones AS p ON t.primaryKey = p.refKey 
WHERE p.phone = ?
Bill Karwin
sumber
1
Dan jika karena alasan apa pun Anda tidak dapat mengubah tata letak tabel, Anda bisa menulis tampilan yang mewakili data dalam format ini, lalu kueri tampilan.
CodeCaster
10
Tidak, ubah saja tata letak tabel. Itu dia. Aku bosan dengan alasan "Aku tidak bisa mengubahnya." Saya tidak menerimanya lagi. Saatnya belajar bagaimana mengubah sesuatu.
Bill Karwin
15

Semakin dekat Anda bisa dapatkan ini, menggunakan IN:

SELECT * FROM table WHERE 'val' IN (col1, col2, ..., colN) ;

Anda masih harus menulis semua kolom yang ingin Anda periksa.
Dan itu tidak ada bedanya dengan ORekspresi yang Anda miliki, tidak dalam kinerja atau sebaliknya. Ini hanya cara yang berbeda dan setara untuk menulis ekspresi, dengan karakter yang sedikit lebih sedikit.

ypercubeᵀᴹ
sumber
3

Anda perlu melakukannya dalam dua langkah, pertama-tama hasilkan sql seperti (dengan asumsi tabel Anda bernama T dalam skema S:

select concat(' SELECT * FROM t WHERE ''a'' in ('
             , GROUP_CONCAT(COLUMN_NAME)
             , ')')
from INFORMATION_SCHEMA.columns 
where table_schema = 's' 
  and table_name = 't'
  and DATA_TYPE IN ('char','varchar');

Sekarang Anda dapat menjalankan string ini. Perhatikan bahwa Anda harus mengutip 'a' dengan ekstra '. Jika Anda memasukkan ini sebagai contoh prosedur, Anda bisa menyiapkan dan mengeksekusi string yang dihasilkan.

Saya diuji dengan:

create table t (a char(3), b varchar(5), c int);
insert into t(a,b) values ('a','b'),('b','c'),('c','c');    

Kueri yang dihasilkan di mana:

SELECT * FROM t WHERE 'a' in (a,b)

dan mengeksekusi yang menghasilkan:

a   b   c
---------
a   b   
Lennart
sumber
1

Rasanya sudah setahun sejak saya menanyakan hal ini, tetapi saya hanya menemukan apa yang tampaknya menjadi hal yang saya cari! Ini bukan pernyataan SQL, seperti yang saya perkirakan, tetapi APA yang saya inginkan.

Di MySQL Workbench, Anda bisa mengklik kanan tabel atau skema, dan pilih Cari Tabel Data.menu konteks skema

donutguy640
sumber
0

Coba yang ini:

select
    *
from
    _table_
where
    concat('.', col1, '.', col2, '.', col3, '.') like "%.search_value.%";

Ini mengasumsikan bahwa tidak ada .dalam string pencarian Anda. Jika Anda tidak dapat menjamin hal itu, mungkin Anda dapat menggunakan "karakter pemisah" yang berbeda.

Anon0012398193
sumber
1
Bisakah Anda menjelaskan mengapa solusi Anda berhasil? Jawaban hanya kode tidak dianggap sebagai jawaban yang baik di sini.
George.Palacios
itu tidak bekerja. mis. jika pencarian mengandung %atau _kolom mana pun mengandung.
Jasen
1
@ Yasen Anda dapat keluar dari karakter khusus dan menggunakan pemisah yang berbeda.
Anon0012398193
@ George.Palacios - apa yang Anda temukan tidak jelas?
Anon0012398193
memilih pemisah yang benar bisa sangat sulit. pendekatan ini sangat sulit dilakukan dengan benar
Jasen
0

Solusi paling sederhana adalah melakukan

mysqldump ... --skip-extended-insert db table | grep 'val'

Kecuali jika val adalah sesuatu yang umum terjadi dalam sintaks sql.

jkavalik
sumber
Saya harap Anda mengejek saya, karena alternatifnya adalah Anda pikir ini akan membantu.
donutguy640
1
Saya jelas tidak. Ini adalah cara yang valid untuk menemukan sesuatu jika Anda tidak tahu "di mana" itu ada di db / table. Grep akan mengembalikan seluruh baris (termasuk nama tabel) di mana nilainya ada. Ini bukan SQL dan tidak terlalu berguna jika Anda ingin memproses output secara terprogram, tetapi sederhana dan cukup cepat.
jkavalik
-2

Coba ini.

SELECT *
FROM table
WHERE CONCAT(col1,' ',col2,' ',col3)="val val val";

CONCAT () digunakan untuk memisahkan nilai kolom yang sama seperti di sini Anda dapat memisahkan kolom Anda dengan ruang untuk menentukan hasil yang lebih baik di dalam fungsi dan memeriksa nilai juga string yang dipisahkan dengan ruang dan hasilnya ada di tangan Anda.

Deepak
sumber
-3

Itu dimungkinkan dengan menggunakan database information_schema, pada dasarnya kami hanya akan mencantumkan semua kolom dari tabel tertentu kemudian menggunakan GROUP_CONCAT untuk mendaftar mereka sebagai satu baris kemudian memberi mereka dalam pernyataan IN.

select * from db.table where 'value' in (select GROUP_CONCAT(COLUMN_NAME) from INFORMATION_SCHEMA.columns where table_schema = 'db' and table_name = 'table');

Ini hanya akan mengembalikan satu baris jika 'nilai' ada di semua kolom.

Rodie
sumber
1
Apakah yang Anda maksud if 'value' is present in any of the columns? Selain itu, Anda dapat menambahkan predikat untuk tipe string seperti: `dan DATA_TYPE IN ('char', 'varchar')`
Lennart
1
Ini akan melakukannya, dan mencapai tujuan OP untuk menghindari penamaan kolom secara eksplisit. Ini bukan wildcard, tetapi GROUP_CONCAT terhadap skema informasi sama baiknya dengan wildcard dari semua nama kolom.
tbrookside
2
Saya mengalami masalah dalam menjalankan ini. Saya mengganti db dan tabel dengan nama skema dan tabel saya, apakah ada hal lain yang dimaksudkan sebagai pengganti untuk nama sebenarnya? Juga, saya mencoba pernyataan dalam sendiri, dan saya menyadari bahwa itu CONCAT nama kolom, bukan data baris. Itukah yang kamu maksud?
donutguy640
4
Dengan segala hormat, ini salah. Kueri Anda akan membandingkan 'nilai' dengan nama kolom, bukan isinya . Saya harus memberikan ini downvote.
Bill Karwin
4
Lebih akurat, ini akan membandingkan 'nilai' string dengan string yang merupakan daftar nama kolom yang dipisahkan koma - pada dasarnya sama dengan where 'value' in ('col1,col2,col3…').
Andriy M