2013-06-19 9 views
14

Es fühlt sich ziemlich einfach an, außer MySQL.IF Bedingung Abfrage durchführen, sonst Abfrage durchführen

Grundsätzlich muss ich wechseln, welche Art von Index ich zusammen mit ein paar anderen Bedingungen verwende, basierend darauf, wie viele Ergebnisse ein bestimmter Ausdruck zurückgibt.

etwas in der Art von:

IF (SELECT COUNT(*) FROM table WHERE term LIKE "term") > 4000 
    EXECUTE QUERY A 
ELSE 
    EXECUTE QUERY B 

Ist das möglich in einer MySQL-Anweisung?

EDIT:

Abfrage A:

SELECT id 
FROM table_a 
FORCE INDEX(id) 
JOIN table_b ON table_a.id = table_b.id 
WHERE term LIKE "term" 
ORDER BY date 
LIMIT 100; 

Abfrage B:

SELECT id 
FROM table_a 
FORCE INDEX(term) 
JOIN table_b ON table_a.id = table_b.id 
WHERE term LIKE "term" 
GROUP BY term # These lines would be included for a few conditions not mentioned above.. but are necessary 
HAVING COUNT = 1 # same... 
ORDER BY date 
LIMIT 100; 

Der Grund für die Abfrage Schalter I dramatisch anderes Ergebnis Zeiten zu erhalten, basierend auf der Popularität des "Begriff".

+2

Was sind 'QUERY A' und' QUERY B' spezifisch? SQL lässt normalerweise zu, dass diese Situation mit einer kreativen "WHERE" -Klausel behandelt wird, aber wir können nicht sagen, es sei denn, wir wissen, ob A & B ausreichend miteinander verwandt sind. –

+1

... Ansonsten erlaubt MySQL nur die Verwendung von Ablaufsteuerungslogik in Funktionen, Triggern und gespeicherten Prozeduren - nicht in regulären Abfragen. –

+0

In der Theorie - ja (mit Hilfe von 'CASE' Statement und Joins), aber es hängt davon ab, ob die Anzahl der Felder und Datensätze in beiden Abfragen übereinstimmen.Sie sollten diese beiden zusammen mit Testdaten veröffentlichen, damit wir antworten können. –

Antwort

16

EDIT: Was ich sagte, unten über eine gespeicherte Prozedur erfordert nicht wahr ist. Versuchen Sie folgendes:

SELECT CASE WHEN ((SELECT COUNT(*) FROM table WHERE term LIKE "term") > 4000) 
    THEN <QUERY A> 
    ELSE <QUERY B> 
END 

Dies ist in der Tat ein Fall Ausdruck, und es funktioniert gut außerhalb eines gespeicherten proc :-)

Zum Beispiel:

mysql> SELECT CASE WHEN (5 > 4) THEN (SELECT 'foo') ELSE (SELECT 'bar') END; 
+---------------------------------------------------------------------+ 
| CASE WHEN (5 > 4) THEN (SELECT 'foo') ELSE (SELECT 'bar') END | 
+---------------------------------------------------------------------+ 
| foo                 | 
+---------------------------------------------------------------------+ 
1 row in set (0.01 sec) 

mysql> SELECT CASE WHEN (3 > 4) THEN (SELECT 'foo') ELSE (SELECT 'bar') END; 
+---------------------------------------------------------------------+ 
| CASE WHEN (3 > 4) THEN (SELECT 'foo') ELSE (SELECT 'bar') END | 
+---------------------------------------------------------------------+ 
| bar                 | 
+---------------------------------------------------------------------+ 
1 row in set (0.00 sec) 

Alte Antwort unten für historische Interesse, da es bereits versammelt Bewertungen:

Sie können die unten genannten ich denke, aber nur in einer gespeicherten Prozedur:

CASE (SELECT COUNT(*) FROM table WHERE term LIKE "term") > 4000 
    WHEN 1 THEN <QUERY A> 
    ELSE <QUERY B> 
END CASE 

Dies ist eine CASE Aussage, im Unterschied zu einem CASE Ausdruck ... https://dev.mysql.com/doc/refman/5.0/en/case.html hat mehr blutigen Details.

Eigentlich vermute ich im Allgemeinen, wenn Sie verschiedene Abfragen bedingt ausführen wollen, müssen Sie in Richtung gespeicherte Prozeduren suchen - ich könnte falsch liegen, aber das ist mein Bauchgefühl an diesem Punkt. Wenn Sie es tun können, wird es wahrscheinlich mit CASE-Ausdrücken sein!

Eine letzte Bearbeitung: In irgendeinem realen Beispiel würde ich wahrscheinlich das bedingte Bit in meiner Anwendung machen und einfach an SQL (oder an ein ORM, das mein SQL generieren würde) übergeben, sobald ich entschieden habe, was ich tun soll suchen nach.

+1

Sie sollten wahrscheinlich auch erwähnen, dass dies nur funktioniert, wenn die Abfragen nur 1 Zeile zurückgeben. Andernfalls erhalten Sie eine Fehlermeldung, dass die Unterabfrage mehr als 1 Zeile zurückgibt. – fancyPants

4

Versuchen:

select coalesce(i.id, t.id) id 
from (SELECT COUNT(*) countterm FROM table WHERE term LIKE "term") c 
left join 
    (SELECT id, date 
     FROM table_a 
     FORCE INDEX(id) 
     JOIN table_b ON table_a.id = table_b.id 
     WHERE term LIKE "term") i on countterm > 4000 
left join 
    (SELECT id, date 
     FROM table_a 
     FORCE INDEX(term) 
     JOIN table_b ON table_a.id = table_b.id 
     WHERE term LIKE "term" 
     GROUP BY term 
     HAVING COUNT = 1) t on countterm <= 4000 
ORDER BY coalesce(i.date, t.date) 
LIMIT 100; 
+2

Ich mag das, weil es die richtige Ausgabe gibt, aber es führt beide Abfragen aus und ich bin sicher, dass OP das vermeiden will. – Bohemian

+0

@Bohemian: Wird die Unterabfrage tatsächlich ausgeführt, wenn die Bedingung 'join ... on' (zur Hauptabfrage) falsch ist? –

+1

Ich denke schon, weil die ON-Bedingung ist eine Mini-Where-Klausel - ein Filter - für die verbundenen Zeilen, und die Unwahrheit der Bedingung kann nicht optimiert werden (keine Möglichkeit, vorher zu wissen, dass es falsch sein wird). Ich könnte mich irren ... – Bohemian

Verwandte Themen