MySQL - Cómo verificar un valor en todas las columnas

11

Tengo curiosidad, ¿hay una buena manera de buscar en todas las columnas un valor dado? Para mis propósitos, no es necesario que sea rápido, es solo una cosa única, y realmente no quiero tener que escribir cada nombre de campo. Eso es precisamente lo que haré por ahora, pero creo que seguramente hay una mejor manera.

Me gustaría convertir esto:

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

dentro de esto:

SELECT * FROM table WHERE * = 'val'

... o, mejor aún (aunque lo dudo seriamente ...)

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

Encontré esto , que parece un poco no muy cerca, pero no encuentro nada más cerca:

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

La diferencia es que busca en una selección de columnas los valores especificados, mientras que estoy tratando de buscar en TODAS las columnas un solo valor.

Sin embargo, no es importante, como dije más que nada, solo tengo curiosidad

donutguy640
fuente

Respuestas:

23

SQL no proporciona una buena forma de hacerlo porque probablemente no sea un buen diseño de tabla tener N columnas que puedan tener valores en el mismo dominio. Esto es potencialmente un caso de "grupos repetitivos" como si tiene columnas phone1, phone2, phone3, ... phoneN.

Si tiene varias columnas que tienen el mismo dominio lógico de valores, podría ser un caso en el que es un atributo de valores múltiples (como en el ejemplo de los teléfonos). La forma estándar de almacenar atributos de valores múltiples es como varias filas en otra tabla, con una referencia a la fila a la que pertenecen en la tabla primaria.

Si hace eso, solo tiene que buscar el valor específico en una columna de la tabla dependiente.

SELECT t.* FROM mytable AS t
JOIN phones AS p ON t.primaryKey = p.refKey 
WHERE p.phone = ?
Bill Karwin
fuente
1
Y si por alguna razón no puede cambiar el diseño de la tabla, puede escribir una vista que represente los datos en este formato y luego consultar la vista.
CodeCaster
10
No, solo cambia el diseño de la tabla. Eso es. Estoy cansado de la excusa "No puedo cambiarlo". Ya no acepto eso. Es hora de aprender a cambiar las cosas.
Bill Karwin
15

Lo más cerca que puede acercarse es esto, usando IN:

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

Todavía tiene que escribir todas las columnas que desea verificar.
Y no es diferente de la ORexpresión que tiene, ni en el rendimiento ni de otra manera. Esta es solo una forma diferente y equivalente de escribir la expresión, con un poco menos de caracteres.

ypercubeᵀᴹ
fuente
3

Debe hacerlo en dos pasos, primero genere el sql like (suponiendo que su tabla se llame T en el esquema 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');

Ahora puedes ejecutar esta cadena. Tenga en cuenta que debe citar la 'a' con extra '. Si pone esto, por ejemplo, en un procedimiento, puede preparar y ejecutar la cadena que se generó.

Probé con:

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

La consulta generada donde:

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

y ejecutar eso da como resultado:

a   b   c
---------
a   b   
Lennart
fuente
1

¡Parece que ha pasado un año desde que pregunté esto, pero me topé con lo que parece ser exactamente lo que estaba buscando! No es una declaración SQL, como estaba anticipando, pero HACE lo que quería.

En MySQL Workbench, puede hacer clic con el botón derecho en la tabla o el esquema y elegir Buscar datos de tabla.menú contextual del esquema

donutguy640
fuente
0

Prueba este:

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

Esto supone que no hay .en su cadena de búsqueda. Si no puede garantizarlo, tal vez pueda usar un "carácter separador" diferente.

Anon0012398193
fuente
1
¿Podría explicar por qué su solución funciona, por favor? Las respuestas de solo código no se consideran una buena respuesta aquí.
George.Palacios
No funciona. por ejemplo, si la búsqueda contiene %o _alguna columna contiene.
Jasen
1
@Jasen Puedes escapar de los caracteres especiales y usar un separador diferente.
Anon0012398193
@ George.Palacios: ¿qué es lo que no está claro?
Anon0012398193
elegir el separador correcto podría ser muy difícil. este enfoque es muy difícil de hacer bien
Jasen
0

La solución más simple es hacer

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

A menos que el val sea ​​algo que sea una ocurrencia común en la sintaxis sql.

jkavalik
fuente
Espero que te estés burlando de mí, ya que la alternativa es que pensaste que esto sería útil.
donutguy640
1
Definitivamente no lo soy. Es una forma válida de encontrar algo si no sabe "dónde" está en la tabla db /. El grep devolverá las filas completas (incluido el nombre de la tabla) donde está presente el valor. No es SQL y no es muy útil si desea procesar la salida mediante programación, pero es simple y bastante rápido.
jkavalik
-2

Prueba esto.

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

CONCAT () se usa para separar los valores de columna de la misma manera que aquí puede separar su columna con espacio para especificar el mejor resultado dentro de la función y verificar el valor también separó la cadena con espacio y el resultado está en su mano.

Deepak
fuente
-3

Es posible mediante el uso de la base de datos information_schema, básicamente solo enumeraremos todas las columnas de una tabla específica, luego usaremos GROUP_CONCAT para enumerarlas como una línea y luego alimentarlas en una declaración 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');

Esto solo devolverá una fila si el 'valor' está presente en todas las columnas.

Rodie
fuente
1
Qué quiere decir if 'value' is present in any of the columns? Además, puede agregar un predicado para tipos de cadena como: `y DATA_TYPE IN ('char', 'varchar')`
Lennart
1
Esto lo hará, y logra el objetivo de OP de evitar nombrar explícitamente las columnas. No es un comodín, pero GROUP_CONCAT contra el esquema de información es tan bueno como un comodín de todos los nombres de columna.
tbrookside
2
Tengo problemas para que esto funcione. Reemplacé db y table con mi esquema y nombres de tabla, ¿hay algo más destinado a ser marcadores de posición para los nombres reales? Además, probé la declaración interna por sí sola y me di cuenta de que CONCAT los nombres de columna, en lugar de los datos de una fila. ¿Es eso lo que pretendías?
donutguy640
44
Con el debido respeto, esto está mal. Su consulta comparará el 'valor' con los nombres de las columnas, no con su contenido . Tengo que darle un voto negativo a esto.
Bill Karwin
44
Más exactamente, esto comparará el 'valor' de la cadena con la cadena que es una lista separada por comas de nombres de columnas, esencialmente lo mismo que where 'value' in ('col1,col2,col3…').
Andriy M