Mysql
 sql >> Database >  >> RDS >> Mysql

Valori separati da virgola nella clausola MySQL IN

Basandosi sull'esempio FIND_IN_SET() di @Jeremy Smith, puoi farlo con un join in modo da non dover eseguire una sottoquery.

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

Questo è noto per funzionare molto male, poiché deve eseguire scansioni di tabelle, valutando la funzione FIND_IN_SET() per ogni combinazione di righe in table e locations . Non può utilizzare un indice e non c'è modo di migliorarlo.

So che hai detto che stai cercando di ottenere il meglio da una cattiva progettazione di database, ma devi capire quanto sia drasticamente negativo.

Spiegazione:Supponiamo che io debba chiederti di cercare tutti in un elenco telefonico la cui prima, metà o ultima iniziale è "J". In questo caso non è possibile che l'ordine ordinato del libro aiuti, dal momento che devi comunque scansionare ogni singola pagina.

Il LIKE la soluzione data da @fthiella ha un problema simile per quanto riguarda le prestazioni. Non può essere indicizzato.

Vedi anche la mia risposta a La memorizzazione di un elenco delimitato in una colonna del database è davvero così male? per altre insidie ​​di questo modo di memorizzare i dati denormalizzati.

Se puoi creare una tabella supplementare per memorizzare un indice, puoi mappare le posizioni a ciascuna voce nell'elenco delle città:

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

Supponendo che tu abbia una tabella di ricerca per tutte le possibili città (non solo quelle menzionate nella table ) puoi sopportare l'inefficienza una volta per produrre la mappatura:

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;

Ora puoi eseguire una query molto più efficiente per trovare le voci nella tua table :

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

Questo può utilizzare un indice. Ora devi solo fare attenzione che qualsiasi INSERT/UPDATE/DELETE di righe in locations inserisce anche le righe di mappatura corrispondenti in location2city .