Tengo una columna en una tabla donde guardo las múltiples identificadores separados por comas del.
Hay una manera en la que puede utilizar el valor de esta columna en el «EN» la cláusula de una consulta.

La columna(city) tiene valores como 6,7,8,16,21,2

Necesito usar como

select * from table where e_ID in (Select city from locations where e_Id=?)

Estoy satisfecho con Crozin la respuesta, pero estoy abierto a sugerencias, opiniones y opciones.

Siéntase libre de compartir sus puntos de vista.

InformationsquelleAutor Sashi Kant | 2012-05-07

10 Comentarios

  1. 28

    Edificio en el FIND_IN_SET() ejemplo de @Jeremy Smith, usted puede hacerlo con una combinación de modo que usted no tiene 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 = ?

    Esto es conocido para llevar a cabo muy mal, ya que tiene que ver tabla exploraciones, la evaluación de la FIND_IN_SET() función para cada combinación de filas en table y locations. Se puede hacer uso de un índice, y no hay manera de mejorarlo.

    Yo sé que usted dijo que están tratando de hacer lo mejor de un mal diseño de base de datos, pero usted debe entender cómo drásticamente malo es esto.

    Explicación: Supongamos que yo le preguntara a usted para buscar que todos en un libro de teléfono cuyo primer, segundo, o la inicial de su apellido es «J.» no Hay manera de que la ordenada de la libreta de ayuda en este caso, ya que usted tiene que escanear cada página individual de todos modos.

    La LIKE solución dada por @fthiella tiene un problema similar en cuanto a rendimiento. No puede ser indexado.

    También ver mi respuesta a Es el almacenamiento de una lista delimitada en una columna de base de datos realmente tan malo? para otros escollos de esta forma de almacenamiento de datos sin normalizar.

    Si usted puede crear una tabla suplementaria para almacenar un índice, puede asignar las ubicaciones para cada entrada en la lista de ciudad:

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

    Suponiendo que se tiene una tabla de búsqueda de todas las posibles ciudades (no sólo los mencionados en el table) puedes soportar la ineficiencia un tiempo para producir la cartografía:

    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 manera mucho más eficiente de consulta para encontrar las 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 sólo tiene que tener cuidado de que cualquier INSERTAR/ACTUALIZAR/ELIMINAR de las filas en locations también inserta la correspondiente asignación de filas en location2city.

    • +1 para una lúcida explicación
    • He usado el FIND_IN_SET opción. Esta es la mejor de las respuestas de los disponibles aquí. En lugar de combinaciones y de las sub consultas en esta se adapte mejor. Pero a menos que sea muy importante que no trate de almacén de valores separados por comas en una columna. Que no encaja en el RDBMS. He utilizado debido a que la tabla y los datos fueron creados mucho antes y había gran cantidad de datos que no me quiero arriesgar por la Transferencia de Datos.
    • Muchas gracias por tu sugerencia y muchas Gracias Bill.
  2. 25

    De MySQL punto de vista no está almacenar múltiples identificadores separados por comas usted está almacenando un texto valor, que tiene exactamente el mismo meaing como «Hola Mundo» o «me gustan las tortas!» – es decir, no tiene ningún tipo de meaing.

    Lo que tienes que hacer es crear una separada de la tabla que unirá dos objetos de la base de datos juntos. Lea más acerca de muchos-a-muchos o uno-a-muchos (dependiendo de sus necesidades) relaciones basadas en SQL bases de datos.

    • Gracias por tu sugerencia y acepto que el diseño es pobre, pero tengo algunas limitaciones que las que no puedo cambiar. Es allí una manera de implementar esto….
    • Obviamente él está pidiendo una solución……….
  3. 24

    En lugar de usar IN en su consulta, uso FIND_IN_SET (docs):

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

    Las habituales advertencias acerca de la primera forma de la normalización de aplicar (la base de datos no debería almacenar varios valores en una sola columna), pero si estás atascado con ella, entonces la instrucción anterior debe ayudar.

    • Gracias por tu respuesta. Esto es muy útil. Cualquier luz en el rendimiento?
    • El rendimiento va a ser relativamente pobre, porque FIND_IN_SET puede utilizar cualquiera de los índices. Si usted está preocupado por el rendimiento (y tienen la autoridad para hacerlo), que realmente se necesita dividir su locations.city columna en otra tabla el uso de 1nf, y entonces usted puede utilizar los índices para ayudar a su rendimiento.
    • Como @JeremySmyth dice, la teoría es almacenar una lista separada por comas de los números en una columna viola una regla básica de diseño de base de datos, la atomicidad de la regla (una célula, un valor). Por lo tanto, sería mejor para el rediseño de que. PERO, si las restricciones no permiten que ir con FIND_IN_SET.
  4. 21

    Esto no utilizar EN la cláusula, pero se debe hacer lo que usted necesita:

    Select *
    from table
    where
      CONCAT(',', (Select city from locations where e_Id=?), ',')
      LIKE
      CONCAT('%,', e_ID, ',%')

    pero usted tiene que asegurarse de que e_ID no contiene comas o cualquier jolly carácter.

    por ejemplo,

    CONCAT(',', '6,7,8,16,21,2', ',') returns ',6,7,8,16,21,2,'
    
    e_ID=1  --> ',6,7,8,16,21,2,' LIKE '%,1,%'  ? FALSE
    e_ID=6  --> ',6,7,8,16,21,2,' LIKE '%,6,%'  ? TRUE
    e_ID=21 --> ',6,7,8,16,21,2,' LIKE '%,21,%' ? TRUE
    e_ID=2  --> ',6,7,8,16,21,2,' LIKE '%,2,%'  ? TRUE
    e_ID=3  --> ',6,7,8,16,21,2,' LIKE '%,3,%'  ? FALSE
    etc.
    • +1 @fthiella el más simple de todos hace que las mejores respuestas 🙂 y me gusta ejemplos de código en respuestas y preguntas 😀
    • sí … convertir la comparación campo de int a string, y el uso como. Esto funciona. Sé que el problema es causado por una mala DB de diseño, pero por desgracia a veces tenemos que trabajar con esta mala DB de diseño, a veces sin tiempo suficiente para hacer una reingeniería de la misma.
  5. 7

    esta en para oracle ..aquí la concatenación de cadenas se realiza por wm_concat

    select * from table where e_ID in (Select wm_concat(city) from locations where e_Id=?)

    sí estoy de acuerdo con raheel shan .. con el fin de poner este «en» cláusula tenemos que hacer que la columna en la fila de abajo el código que hacer ese trabajo.

    select * from table  where to_char(e_ID) 
    in (
      select substr(city,instr(city,',',1,rownum)+1,instr(city,',',1,rownum+1)-instr(city,',',1,rownum)-1) from 
      (
      select ','||WM_CONCAT(city)||',' city,length(WM_CONCAT(city))-length(replace(WM_CONCAT(city),','))+1 CNT from locations where e_Id=? ) TST 
      ,ALL_OBJECTS OBJ where TST.CNT>=rownum
        ) ;
  6. 6

    debe utilizar

    FIND_IN_SET Devuelve la posición de valor en la cadena de valores separados por comas

    mysql> SELECT FIND_IN_SET('b','a,b,c,d');
        -> 2
  7. 6

    No sé si esto es lo que se quiere lograr. Con MySQL no es función de concatenar los valores de un grupo GROUP_CONCAT

    Usted puede intentar algo como esto:

    select * from table where e_ID in (Select GROUP_CONCAT(city SEPARATOR ',') from locations where e_Id=?)
  8. 6

    Usted necesita para «DIVIDIR» la ciudad de los valores de la columna. Será como:

    SELECT *
      FROM table
     WHERE e_ID IN (SELECT TO_NUMBER(
                                     SPLIT_STR(city /*string*/
                                               , ',' /*delimiter*/
                                               , 1 /*start_position*/
                                               )
                                     )
                      FROM locations);

    Usted puede leer más acerca de la de MySQL split_str función aquí: http://blog.fedecarg.com/2009/02/22/mysql-split-string-function/

    También, he utilizado el TO_NUMBER función de Oracle aquí. Sustitúyalo con un adecuado MySQL función.

  9. 5

    Se lleva a filas para tomar separados por comas columna de búsqueda no va a hacer lo que quieras, pero si usted proporciona datos como este (‘1′,’2′,’3’) esto funciona, pero no se puede guardar los datos, como en el campo de lo que se inserta en la columna va a tomar todo el asunto como una cadena.

  10. 2

    Puede crear una declaración preparada dinámicamente como este

    set @sql = concat('select * from city where city_id in (',
                      (select cities from location where location_id = 3),
                      ')');
    prepare in_stmt from @sql;
    execute in_stmt;
    deallocate prepare in_stmt;

Dejar respuesta

Please enter your comment!
Please enter your name here