Saltar al contenido

Valores separados por comas en la cláusula “IN” de MySQL

Si encuentras algo que te causa duda puedes dejarlo en la sección de comentarios y te ayudaremos lo mas rápido que podamos.

Solución:

Sobre la base del ejemplo FIND_IN_SET() de @Jeremy Smith, puede hacerlo con una combinación para no tener que ejecutar una subconsulta.

SELECT * FROM table t
JOIN locations l ON FIND_IN_SET(t.e_ID, l.city) > 0
WHERE l.e_ID = ?

Se sabe que esto funciona muy mal, ya que tiene que hacer escaneos de tablas, evaluando la función FIND_IN_SET() para cada combinación de filas en table y locations. No puede hacer uso de un índice, y no hay forma de mejorarlo.

Sé que dijo que está tratando de sacar lo mejor de un mal diseño de base de datos, pero debe comprender cuán drásticamente malo es esto.

Explicación: suponga que le pido que busque a todos en una guía telefónica cuya primera, segunda o última inicial sea “J”. No hay forma de que el orden ordenado del libro ayude en este caso, ya que de todos modos tienes que escanear cada página.

los LIKE solución dada por @fthiella tiene un problema similar con respecto al rendimiento. No se puede indexar.

También vea mi respuesta a ¿Es realmente tan malo almacenar una lista delimitada en una columna de base de datos? para otras trampas de esta forma de almacenar datos desnormalizados.

Si puede crear una tabla complementaria para almacenar un índice, puede asignar las ubicaciones a cada entrada en la lista de ciudades:

CREATE TABLE location2city (
 location INT,
 city INT,
 PRIMARY KEY (location, city)
); 

Suponiendo que tiene una tabla de búsqueda para todas las ciudades posibles (no solo las mencionadas en el table) puede soportar la ineficiencia una vez para producir el mapeo:

INSERT INTO location2city (location, city)
  SELECT l.e_ID, c.e_ID FROM cities c JOIN locations l
  ON FIND_IN_SET(c.e_ID, l.city) > 0;

Ahora puede ejecutar una consulta mucho más eficiente para encontrar entradas en su table:

SELECT * FROM location2city l
JOIN table t ON t.e_ID = l.city
WHERE l.e_ID = ?;

Esto puede hacer uso de un índice. Ahora solo debe tener cuidado de que cualquier INSERCIÓN / ACTUALIZACIÓN / ELIMINACIÓN de filas en locations también inserta las filas de mapeo correspondientes en location2city.

Desde el punto de vista de MySQL, no está almacenando múltiples identificaciones separadas por comas, está almacenando un texto valor, que tiene exactamente el mismo significado que “Hola mundo” o “¡Me gustan los pasteles!” – es decir, no tiene ningún significado.

Lo que tienes que hacer es crear una tabla separada que vincule dos objetos de la base de datos. Obtenga más información sobre las relaciones de muchos a muchos o de uno a muchos (según sus requisitos) en bases de datos basadas en SQL.

En lugar de usar IN en su consulta, utilice FIND_IN_SET (documentos):

SELECT * FROM table 
WHERE 0 < FIND_IN_SET(e_ID, (
             SELECT city FROM locations WHERE e_ID=?))

Se aplican las advertencias habituales sobre la normalización de la primera forma (la base de datos no debe almacenar varios valores en una sola columna), pero si no puede seguir con ella, entonces la declaración anterior debería ayudar.

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *