MySQL - Як перевірити значення у всіх стовпцях


11

Мені цікаво, чи є хороший спосіб пошуку всіх стовпців за заданим значенням? Для моїх цілей це зовсім не обов'язково, це просто одноразова штука, і мені не дуже хочеться вводити кожну назву поля. Саме цим я і зараз займаюся, але, думаю, напевно є кращий шлях.

Я хотів би перетворити це:

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

в це:

SELECT * FROM table WHERE * = 'val'

... або, ще краще (хоча я в цьому серйозно сумніваюся ...)

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

Я виявив це , яке здається не дуже близьким, але я не знаходжу нічого ближчого:

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

Різниця полягає в тому, що відбувається пошук вибору стовпців для вказаних значень, тоді як я намагаюся шукати ВСІ стовпці для одного значення.

Хоча це не важливо, як я сказав більше, ніж усе, що мені просто цікаво

Відповіді:


23

SQL не забезпечує хорошого способу цього, тому що, мабуть, не дуже гарний дизайн таблиці, щоб було N стовпців, які можуть мати значення в одному домені Це потенційно випадок «повторюваних груп» , як якщо у вас є стовпці phone1, phone2, phone3, ... phoneN.

Якщо у вас є ряд стовпців, які мають однакову логічну область значень, це може бути випадок, коли це багатозначний атрибут (наприклад, на прикладі телефонів). Стандартний спосіб зберігання багатозначних атрибутів - це декілька рядків в іншій таблиці з посиланням на рядок, якому вони належать у первинній таблиці.

Якщо ви це зробите, то вам потрібно лише шукати конкретне значення в одному стовпчику залежної таблиці.

SELECT t.* FROM mytable AS t
JOIN phones AS p ON t.primaryKey = p.refKey 
WHERE p.phone = ?

1
І якщо з будь-якої причини ви не можете змінити макет таблиці, ви можете написати перегляд, який представляє дані в цьому форматі, а потім запитувати подання.
CodeCaster

10
Ні, просто змінити макет таблиці. Це воно. Я втомився від виправдання "я не можу це змінити". Я більше не приймаю цього. Пора навчитися змінювати речі.
Білл

15

Чим ближче ви можете це зробити, використовуючи IN:

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

Вам ще потрібно записати всі стовпці, які ви хочете перевірити.
І це нічим не відрізняється від ORвисловлення, яке ви маєте, не у виконанні чи іншому. Це просто інший, рівнозначний спосіб написання виразу з трохи меншими символами.


3

Вам потрібно зробити це в два етапи, спочатку генеруйте подібний sql (якщо припустимо, що ваша таблиця названа T у схемі 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');

Тепер ви можете виконати цей рядок. Зауважте, що ви повинні цитувати "a" із додатковими ". Якщо ви поставите це, наприклад, для процедури, ви можете підготувати і виконати створений рядок.

Я тестував:

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

Запит генерується де:

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

і виконання цього результату:

a   b   c
---------
a   b   

1

Схоже, минув рік, як я запитав це, але я просто натрапив на те, що, здається, саме те, що я шукав! Це не заява SQL, як я очікував, але це робить те, що я хотів.

У MySQL Workbench ви можете клацнути правою кнопкою миші таблицю або схему та обрати пошук даних таблиці.контекстне меню схеми


0

Спробуйте це:

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

Це передбачає, що .у вашому рядку пошуку немає. Якщо ви не можете цього гарантувати, можливо, ви можете використовувати інший "розділовий символ".


1
Чи можете ви пояснити, чому ваше рішення працює, будь ласка? Тут лише відповіді на код не сприймаються як хороша відповідь.
Джордж Палачіос

це не працює. Наприклад, якщо пошук містить %або _будь-який стовпець містить.
Ясен,

1
@Jasen Ви можете уникати спеціальних символів і використовувати інший роздільник.
Anon0012398193

@ George.Palacios - що це ти вважаєш незрозумілим?
Anon0012398193

вибрати правильний роздільник може бути дуже важким. такий підхід дуже важко зробити правильно
Ясен

0

Найпростіше рішення

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

Якщо тільки val не є звичайним явищем у синтаксисі sql.


Я сподіваюся, що ви знущаєтесь над мною, як альтернатива тому, що ви думали, що це буде корисно.
donutguy640

1
Я точно не є. Це дійсний спосіб знайти щось, якщо ви не знаєте "де" це в db / table. Grep поверне цілі рядки (включаючи назву таблиці), де є значення. Це не SQL і не дуже корисно, якщо ви хочете обробити вихід програмно, але це просто і досить швидко.
jkavalik

-2

Спробуйте це.

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

CONCAT () використовується для розділення значень стовпців так само, як тут ви можете розділити свій стовпець пробілом, щоб вказати кращий результат всередині функції та перевірити значення також розділеного рядка з пробілом, і результат знаходиться у вашій руці.


-3

Це можливо, використовуючи базу даних information_schema, ми в основному просто перерахуємо всі стовпці певної таблиці, а потім використовуємо GROUP_CONCAT, щоб перерахувати їх як один рядок, а потім подати їх у оператор 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');

Це поверне лише рядок, якщо "значення" присутнє у всіх стовпцях.


1
Ви маєте на увазі if 'value' is present in any of the columns? Крім того, ви можете додати предикат для типів рядків типу: `і DATA_TYPE IN ('char', 'varchar')`
Lennart

1
Це зробить це і досягне мети ОП уникнути явного іменування стовпців. Це не майна, але GROUP_CONCAT проти інформаційної схеми так само добре, як і підкреслення всіх назв стовпців.
tbrookside

2
У мене виникають труднощі з тим, щоб це працювати. Я замінив db і table на свою схему та назви таблиць, чи є ще щось, що призначене для заповнення фактичних імен? Крім того, я спробував внутрішнє висловлювання самостійно і розумію, що він КОНЦАТУЄ назви стовпців, а не дані рядка. Це те, що ви задумали?
donutguy640

4
При всій повазі це неправильно. Ваш запит буде порівнювати "значення" з назвами стовпців, а не їх вмістом . Я маю дати це голосування.
Білл

4
Точніше, це порівняє рядок 'value' з рядком, який є розділеним комою списком імен стовпців - по суті такий же, як where 'value' in ('col1,col2,col3…').
Андрій М
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.