2017-12-11 6 views
4

Ich habe eine Tabelle, die Transaktionen aufzeichnet. Ich möchte alle IDs auszuwählen, die genau 4 Transaktionen Wert 2000, aber dann diejenigen auszuschließen, die eine einzelne Transaktion von 2500.Mysql durch Bedingung auswählen, wenn keine andere Bedingung erfüllt ist

SELECT t.tuserid, COUNT(*) AS CNT 
    FROM transactions t 
WHERE t.amt = 2000 
GROUP BY t.tuserid 
HAVING CNT = 4; 

Dieser Teil einfach genug ist, aber ich bin mir nicht sicher, wie man Schließen Sie effizient jeden aus, der eine Transaktion mit einem t.amt = 2500 hat. Wäre eine einfache Unterabfrage für die where-Klausel am effizientesten?

SELECT t.tuserid, COUNT(*) AS CNT 
    FROM transactions t 
WHERE t.amt = 2000 
AND t.tuserid NOT IN (SELECT x.tuserid FROM transactions x WHERE x.amt=2500) 
GROUP BY t.tuserid 
HAVING CNT = 4; 

Die Transaktionen Tabelle ist groß und ich bin mir nicht sicher, dass eine Unterabfrage der effizienteste Weg ist, diesen Prozess zu laufen.

Antwort

3

Ja eine Sub-Abfrage ist in Ordnung hier zu verwenden sein. Ihre Unterabfrage verwendet keine "Variablen" aus der äußeren Abfrage, daher handelt es sich nicht um eine korrelierte Unterabfrage. Ein Correlated wird normalerweise für jede Zeile der äußeren Abfrage "ausgeführt" und ist oft ein Leistungsproblem.

Ihre Unterabfrage würde nur einmal pro äußerem Abfrageaufruf aufgerufen werden.

Darüber hinaus ist es immer eine gute Idee, über Ihre Indizes nachzudenken, also wäre es eine gute Idee, einen Index auf Ihr verwendetes Feld innerhalb der Where-Klausel zu setzen. Dann sollten beide Abfragen in einer Komplexitätsklasse von O (log (n)) sein, die selbst für große Datentabellen sehr schnell sein sollte.

+0

Danke. Die relevanten Spalten sind indiziert (ich habe hier einige Dinge weggelassen) – Steve

0

Ich habe nicht die Ressourcen, um dies zu testen, aber eine Alternative ohne Unterabfrage kann nur SUM

SELECT 
    t.tuserid, 
    SUM(CASE WHEN t.amt = 2000 THEN 1 ELSE 0 END CASE) AS CNT1, 
    SUM(CASE WHEN t.amt = 2500 THEN 1 ELSE 0 END CASE) AS CNT2 
FROM 
    transactions t 
GROUP BY 
    t.tuserid 
HAVING 
    CNT1 = 4 AND CNT2 = 0; 
Verwandte Themen