MySQL - jak sprawdzić wartość we wszystkich kolumnach

11

Jestem ciekawy, czy istnieje dobry sposób na przeszukanie wszystkich kolumn pod kątem określonej wartości? Dla moich celów wcale nie musi to być szybkie, to po prostu jednorazowa rzecz i naprawdę nie chcę wpisywać każdej nazwy pola. Właśnie to teraz zrobię, ale myślę, że na pewno jest lepszy sposób.

Chciałbym to zmienić:

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

zaangażowany w to:

SELECT * FROM table WHERE * = 'val'

... lub nawet lepiej (choć poważnie w to wątpię ...)

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

Znalazłem to , co wydaje się trochę niezbyt blisko, ale nie znajduję nic bliższego:

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

Różnica polega na tym, że przeszukuje wybrane kolumny dla określonych wartości, podczas gdy próbuję przeszukać WSZYSTKIE kolumny dla jednej wartości.

Nie jest to jednak ważne, jak powiedziałem bardziej niż wszystko, jestem po prostu ciekawy

donutguy640
źródło

Odpowiedzi:

23

SQL nie zapewnia dobrego sposobu na zrobienie tego, ponieważ prawdopodobnie nie jest dobrym projektem tabeli zawierającej N kolumn, które mogą mieć wartości w tej samej domenie. Jest to potencjalnie przypadek „powtarzających się grup” jak gdyby masz kolumny phone1, phone2, phone3... phoneN.

Jeśli masz wiele kolumn, które mają tę samą logiczną domenę wartości, może to być przypadek, w którym jest to atrybut wielowartościowy (jak na przykład telefony). Standardowy sposób przechowywania atrybutów wielowartościowych to wiele wierszy w innej tabeli z odniesieniem do wiersza, do którego należą w tabeli podstawowej.

Jeśli to zrobisz, musisz tylko wyszukać konkretną wartość w jednej kolumnie tabeli zależnej.

SELECT t.* FROM mytable AS t
JOIN phones AS p ON t.primaryKey = p.refKey 
WHERE p.phone = ?
Bill Karwin
źródło
1
A jeśli z jakiegokolwiek powodu nie możesz zmienić układu tabeli, możesz napisać widok reprezentujący dane w tym formacie, a następnie zapytać o widok.
CodeCaster,
10
Nie, po prostu zmień układ tabeli. Otóż ​​to. Mam dość wymówki „Nie mogę tego zmienić”. Już tego nie akceptuję. Czas nauczyć się zmieniać rzeczy.
Bill Karwin
15

Im bliżej możesz to zrobić, używając IN:

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

Nadal musisz napisać wszystkie kolumny, które chcesz sprawdzić.
I nie różni się niczym od ORwyrażenia, które masz, ani w wykonaniu, ani w żaden inny sposób. To tylko inny, równoważny sposób pisania wyrażenia, z nieco mniejszą liczbą znaków.

ypercubeᵀᴹ
źródło
3

Musisz to zrobić w dwóch krokach, najpierw wygeneruj kod SQL podobny (zakładając, że twoja tabela nosi nazwę T w schemacie 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');

Teraz możesz wykonać ten ciąg. Pamiętaj, że musisz zacytować „a” z dodatkowym. Jeśli umieścisz to na przykład w procedurze, możesz przygotować i wykonać wygenerowany ciąg.

Testowałem z:

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

Wygenerowane zapytanie gdzie:

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

i wykonanie tego powoduje:

a   b   c
---------
a   b   
Lennart
źródło
1

Wydaje mi się, że minął rok odkąd go o to poprosiłem, ale natknąłem się na to, co wydaje się być dokładnie tym, czego szukałem! To nie jest instrukcja SQL, jak się spodziewałem, ale robi to, czego chciałem.

W MySQL Workbench możesz kliknąć tabelę lub schemat prawym przyciskiem myszy i wybrać opcję Wyszukaj dane tabeli.menu kontekstowe schematu

donutguy640
źródło
0

Spróbuj tego:

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

Zakłada się, że .w szukanym ciągu nie ma żadnych znaków. Jeśli nie możesz tego zagwarantować, być może możesz użyć innego „znaku separatora”.

Anon0012398193
źródło
1
Czy możesz wyjaśnić, dlaczego Twoje rozwiązanie działa? Odpowiedzi tylko z kodem nie są tutaj postrzegane jako dobra odpowiedź.
George.Palacios
to nie działa. np. jeśli wyszukiwanie zawiera %lub _kolumna zawiera.
Jasen
1
@Jasen Możesz uciec od znaków specjalnych i użyć innego separatora.
Anon0012398193
@ George.Palacios - co jest dla ciebie niejasne?
Anon0012398193
wybranie właściwego separatora może być bardzo trudne. takie podejście jest bardzo trudne do zrobienia
Jasen
0

Najprostsze rozwiązanie to robi

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

Chyba że val jest czymś, co jest częstym zjawiskiem w składni sql.

jkavalik
źródło
Mam nadzieję, że kpisz ze mnie, ponieważ alternatywą jest to, że myślałeś, że to będzie pomocne.
donutguy640,
1
Zdecydowanie nie jestem. Jest to poprawny sposób na znalezienie czegoś, jeśli nie wiesz „gdzie” to jest w db / table. Grep zwróci całe wiersze (w tym nazwę tabeli), w których występuje wartość. To nie jest SQL i nie jest bardzo przydatne, jeśli chcesz przetwarzać dane wyjściowe programowo, ale jest to proste i dość szybkie.
jkavalik,
-2

Spróbuj tego.

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

CONCAT () służy do oddzielania wartości kolumn tak samo, jak tutaj możesz oddzielić kolumnę spacją, aby określić lepszy wynik w funkcji i sprawdzić wartość oddzielonego łańcucha spacją, a wynik jest w twojej ręce.

Deepak
źródło
-3

Jest to możliwe przy użyciu bazy danych information_schema, po prostu wylistujemy wszystkie kolumny określonej tabeli, a następnie użyjemy GROUP_CONCAT, aby wyświetlić je jako jedną linię, a następnie podać je w instrukcji 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');

Zwróci wiersz tylko wtedy, gdy we wszystkich kolumnach występuje „wartość”.

Rodie
źródło
1
Czy masz na myśli if 'value' is present in any of the columns? Ponadto można dodać predykat dla typów ciągów, takich jak: `i DATA_TYPE IN ('char', 'varchar')`
Lennart
1
Uczyni to i osiągnie cel OP polegający na unikaniu jawnego nazywania kolumn. To nie jest symbol wieloznaczny, ale GROUP_CONCAT względem schematu informacyjnego jest tak dobry, jak symbol wieloznaczny wszystkich nazw kolumn.
tbrookside
2
Mam problem z uruchomieniem tego. Zastąpiłem db i table moimi nazwami schematów i tabel, czy jest coś jeszcze, co ma być symbolami zastępczymi rzeczywistych nazw? Wypróbowałem też wewnętrzną instrukcję i zdaję sobie sprawę, że ZAWIERA ona nazwy kolumn, a nie dane wiersza. Czy to właśnie zamierzałeś?
donutguy640,
4
Z całym szacunkiem, to jest złe. Twoje zapytanie porówna „wartość” z nazwami kolumn, a nie z ich zawartością . Muszę to przyznać.
Bill Karwin
4
Dokładniej, to porówna „wartość” ciągu z ciągiem, który jest oddzieloną przecinkami listą nazw kolumn - zasadniczo taką samą jak where 'value' in ('col1,col2,col3…').
Andriy M,