2017-09-05 6 views
1

aus einer Tabelle in sub Ich versuchebeschleunigen (Umschreiben?) Eine nicht Auswahlabfrage

Benutzer zu bekommen a), die bestimmte Kriterien erfüllen, die

in einem Schlüssel/Wert-Kombination in einer Tabelle gehalten wird

OR

b) Benutzer, die diesen Schlüssel/Wert-Kombination überhaupt nicht zu, zum Beispiel also

müssen versuchen, und Benutzer, die in Frankreich leben zu finden oder die noch nicht ihren Standort hinzugefügt, ich bin Verwenden Sie diese (vereinfachte) Abfrage:

Das Problem ist natürlich, dass das Ausführen der ODER-Subselect-Abfrage (wenn es das ist, was es genannt wird) die Abfrage enorm verlangsamt. Und da die vollständige Abfrage ungefähr 5 oder 6 dieser Unterauswahlen enthält, verlangsamt es die Dinge viel zu sehr.

Gibt es vielleicht einen anderen Weg, dies zu tun? Ein schneller Weg?

Antwort

0

Ihre OR-Bedingung als UNION Abfrage ändern statt OR

SELECT * FROM 
    current_users 
    JOIN current_users um_location ON current_users.id = um_location.id 
WHERE 
    um_location.meta_key = 'location' AND um_location.meta_value = 'France' 
UNION 
SELECT * FROM 
    current_users 
    JOIN current_users um_location ON current_users.id = um_location.id 
WHERE 
    current_users.id NOT IN 
    (SELECT current_users.id FROM current_users WHERE 
    current_users.meta_key='location') 
0

Dies ist die prägnanteste möglich sein sollte:

SELECT * 
FROM current_users 
LEFT JOIN current_users AS um_location 
    ON current_users.id = um_location.id 
    AND um_location.meta_key = 'location' 
WHERE um_location.meta_value = 'France' 
    OR um_location.meta_value IS NULL 
; 

... aber als isaace Antwort Hinweise, MySQL nicht behandelt ODER Bedingungen ideal. Also könnte dies besser funktionieren.

SELECT * 
FROM current_users 
LEFT JOIN current_users AS um_location 
    ON current_users.id = um_location.id 
    AND um_location.meta_key = 'location' 
WHERE um_location.meta_value = 'France' 
UNION 
SELECT * 
FROM current_users 
LEFT JOIN current_users AS um_location 
    ON current_users.id = um_location.id 
    AND um_location.meta_key = 'location' 
WHERE um_location.meta_value IS NULL 
; 

..aber es wird wahrscheinlich nur einen Unterschied machen, wenn Sie meta_value indiziert haben; Das Problem ist, dass MySQL Indizes ignoriert, wenn sie mit ODER dargestellt werden.


Edit: Aufgrund der Art der Schema-Design verwendet beginnen, könnte es einige seltsame Probleme mit diesen Abfragen werden mit „Lage“ Einträge als Zeilen auf der linken Seite der Verbindung; versuch dies stattdessen.

SELECT * 
FROM current_users AS non_location 
LEFT JOIN current_users AS um_location 
    ON current_users.id = um_location.id 
    AND um_location.meta_key = 'location' 
WHERE non_location.meta_key != 'location' 
    AND (um_location.meta_value = 'France' 
     OR um_location.meta_value IS NULL 
     ) 
; 
0

Zunächst einmal, vielen Dank für Ihre Anregungen. Leider konnte ich sie nicht zum arbeiten bringen, da die Verbindung

die Datensätze der Benutzer nicht zurückgab, die ihren Standort noch nicht eingegeben hatten.

Allerdings habe ich nach viel Arbeit das Problem gelöst. Es ist nicht elegant, aber es funktioniert:

  1. Erstellen Sie eine temporäre Tabelle mit einer Teilmenge der Benutzer, die einige grundlegende Kriterien erfüllen.
  2. Eine einfache INSERT IGNORE INTO ... SELECT DISTINCT ... VON current_users Hinzufügen der fehlenden "Ort" mit Dummy-Informationen.

Dann wird die letzte Abfrage enthält diese:

um_location.meta_value = 'France' 
or 
um_location.meta_value = 'dummyinfo' 

Es ist nicht mörderisch schnell, aber da dieses ein Prozess ist, der für den Admin-Benutzer im Backend wirkt nur sie leisten zu warten ...;)

Nochmals vielen Dank für Ihre Hilfe!

+0

Ich denke, ich habe das Problem herausgefunden, siehe meine Bearbeitung. – Uueerdo