Mysql
 sql >> Datenbank >  >> RDS >> Mysql

Durch Kommas getrennte Werte in der MySQL IN-Klausel

Aufbauend auf dem FIND_IN_SET()-Beispiel von @Jeremy Smith können Sie dies mit einem Join tun, sodass Sie keine Unterabfrage ausführen müssen.

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

Es ist bekannt, dass dies sehr schlecht funktioniert, da es Tabellen-Scans durchführen muss, wobei die Funktion FIND_IN_SET() für alle ausgewertet wird Kombination von Zeilen in table und locations . Es kann keinen Index verwenden und es gibt keine Möglichkeit, ihn zu verbessern.

Ich weiß, Sie sagten, Sie versuchen, das Beste aus einem schlechten Datenbankdesign zu machen, aber Sie müssen verstehen, wie drastisch schlecht das ist.

Erklärung:Angenommen, ich würde Sie bitten, alle in einem Telefonbuch nachzuschlagen, deren erster, mittlerer oder letzter Anfangsbuchstabe „J“ ist. Die sortierte Reihenfolge des Buches hilft in diesem Fall nicht weiter, da man sowieso jede einzelne Seite scannen muss.

Das LIKE Lösung von @fthiella hat ein ähnliches Problem in Bezug auf die Leistung. Es kann nicht indiziert werden.

Siehe auch meine Antwort auf Ist das Speichern einer Liste mit Trennzeichen in einer Datenbankspalte wirklich so schlecht? für andere Fallstricke dieser Art der Speicherung denormalisierter Daten.

Wenn Sie eine zusätzliche Tabelle erstellen können, um einen Index zu speichern, können Sie die Orte jedem Eintrag in der Städteliste zuordnen:

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

Angenommen, Sie haben eine Nachschlagetabelle für alle möglichen Städte (nicht nur die in der table erwähnten ) können Sie die Ineffizienz einmal ertragen, um das Mapping zu erstellen:

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;

Jetzt können Sie eine viel effizientere Abfrage ausführen, um Einträge in Ihrer table zu finden :

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

Dies kann einen Index verwenden. Jetzt müssen Sie nur noch darauf achten, dass alle INSERT/UPDATE/DELETE von Zeilen in locations fügt auch die entsprechenden Zuordnungszeilen in location2city ein .