2009-06-03 1 views
144

Die Abfrage Ich renne ist wie folgt, aber ich bin immer diese Fehlermeldung:Mit Spalte alias in WHERE-Klausel von MySQL-Abfrage erzeugt einen Fehler

#1054 - Unknown column 'guaranteed_postcode' in 'IN/ALL/ANY subquery'

SELECT `users`.`first_name`, `users`.`last_name`, `users`.`email`, 
SUBSTRING(`locations`.`raw`,-6,4) AS `guaranteed_postcode` 
FROM `users` LEFT OUTER JOIN `locations` 
ON `users`.`id` = `locations`.`user_id` 
WHERE `guaranteed_postcode` NOT IN #this is where the fake col is being used 
(
SELECT `postcode` FROM `postcodes` WHERE `region` IN 
(
    'australia' 
) 
) 

Meine Frage ist: Warum bin ich Sie können keine falsche Spalte in der WHERE-Klausel derselben DB-Abfrage verwenden?

Antwort

334

Sie können Spaltenaliase nur in GROUP BY-, ORDER BY- oder HAVING-Klauseln verwenden.

Standard SQL doesn't allow you to refer to a column alias in a WHERE clause. This restriction is imposed because when the WHERE code is executed, the column value may not yet be determined.

Kopiert von MySQL documentation

Wie in den Kommentaren darauf, statt HAVING verwendet, kann die Arbeit machen. Stellen Sie sicher, dass Sie in diesem WHERE vs HAVING lesen.

+11

+1 für ref (und genauigkeit) –

+1

Prost für die schnelle und genaue antwort! Ich habe einen Blick in die HAVING-Klausel geworfen und einen Weg gefunden, diese Abfrage erfolgreich auszuführen. Danke nochmal. – James

+26

Falls jemand anderes hat gleichen prob wie ich, die den veränderten col in einer Verwendung wurde where-Klausel versagt - die ‚WHERE‘ Swapping für ‚es sofort +1 gute Antwort befestigt ist. – megaSteve4

22

Wie Victor darauf hingewiesen hat, ist das Problem mit dem Alias. Dies kann jedoch vermieden werden, indem man den Ausdruck direkt in die Umsetzung, daß X in y-Klausel:

SELECT `users`.`first_name`,`users`.`last_name`,`users`.`email`,SUBSTRING(`locations`.`raw`,-6,4) AS `guaranteed_postcode` 
FROM `users` LEFT OUTER JOIN `locations` 
ON `users`.`id` = `locations`.`user_id` 
WHERE SUBSTRING(`locations`.`raw`,-6,4) NOT IN #this is where the fake col is being used 
(
SELECT `postcode` FROM `postcodes` WHERE `region` IN 
(
    'australia' 
) 
) 

Aber ich denke, das ist sehr ineffizient, da die Unterabfrage für jede Zeile der äußeren Abfrage ausgeführt werden muss.

+1

@rodion, Ja, ich glaube, das ist ** stark ** langsam und ineffizient. – Pacerier

17

Standard-SQL (oder MySQL) erlaubt nicht die Verwendung von Spaltenaliasnamen in einer WHERE-Klausel, weil

when the WHERE clause is evaluated, the column value may not yet have been determined.

(von MySQL documentation). Sie können den Spaltenwert in der Klausel WHERE berechnen, den Wert in einer Variablen speichern und in der Feldliste verwenden. Zum Beispiel könnten Sie dies tun:

Dies vermeidet die Wiederholung des Ausdrucks, wenn es kompliziert wird, wodurch der Code leichter zu pflegen.

+5

Hat diesen Konflikt nicht mit der Dokumentation [, der sagt] (http://stackoverflow.com/questions/16715504/mysql-define-a-variable-within-select-and-use-it-within-the-same- select/16715618 # 16715618) * "In der Regel sollten Sie einer Benutzervariablen keinen Wert zuweisen und den Wert in derselben Anweisung lesen. Sie erhalten zwar die erwarteten Ergebnisse, dies ist jedoch nicht garantiert." *? – Arjan

+0

Das ist definitiv etwas zu beachten. Es hat immer für mich funktioniert, ich denke, die Reihenfolge der Auswertung der verschiedenen Teile einer Aussage musste festgelegt werden (zuerst WHERE, dann SELECT, dann GROUP BY, ...), aber ich habe keine Referenz dafür – Joni

+0

einige Beispiele: some [Anspruch] (http://stackoverflow.com/questions/16715504/mysql-define-a-variable-within-select-and-use-it-within-the-same-select/24551337# 24551337), dass für sie 'select @code: = SUMME (2), 2 * @ code' in MySQL funktioniert 5.5, aber für mich in 5.6 die zweite Spalte auf dem ersten Aufruf NULL ergibt, und gibt 2 mal * das vorherige Ergebnis * bei führe es nochmals aus. Interessant genug, beide wählen '@code: = 2, 2 * @ code' und' select @code: = rand(), 2 * @ code' scheint in meinem 5.6 (heute) zu funktionieren. Aber diese schreiben und lesen tatsächlich in der SELECT-Klausel; In Ihrem Fall stellen Sie es in WHERE ein. – Arjan

1

Ich verwende MySQL 5.5.24 und der folgende Code funktioniert:

select * from (
SELECT `users`.`first_name`, `users`.`last_name`, `users`.`email`, 
SUBSTRING(`locations`.`raw`,-6,4) AS `guaranteed_postcode` 
FROM `users` LEFT OUTER JOIN `locations` 
ON `users`.`id` = `locations`.`user_id` 
) as a 
WHERE guaranteed_postcode NOT IN --this is where the fake col is being used 
(
SELECT `postcode` FROM `postcodes` WHERE `region` IN 
(
    'australia' 
) 
) 
10

Vielleicht zu spät ist meine Antwort, aber dies kann anderen helfen.

Sie können es mit einer anderen Select-Anweisung einschließen und where-Klausel verwenden.

SELECT * FROM (Select col1, col2,...) as t WHERE t.calcAlias > 0 

calcAlias ​​ist die Alias-Spalte, die berechnet wurde.

+0

Schön und kurz, aber das ist zu vage um nützlich zu sein. – Agamemnus

+0

@Agamemnus, Was meinst du damit? – Pacerier

+0

Die Frage war: "Warum kann ich keine falsche Spalte in der WHERE-Klausel derselben DB-Abfrage verwenden?" Diese Antwort beantwortet diese Frage nicht und es fehlt ein Verb. – Agamemnus

7

können Sie HAVING-Klausel in SELECT Felder berechnet Filter verwenden und Aliase

+0

Ich habe Amerika 1 Jahr nach dir gefunden. Kredit gehören Ihnen: D –

+0

@ fahimg23 - Nicht sicher. Ich habe versucht, einen Grund dafür zu finden, aber ich kann nicht! Beachten Sie jedoch die Unterschiede zwischen 'WHERE' und' HAVING'. Sie sind nicht identisch. https://stackoverflow.com/search?q=where+vs+having – rinogo

+0

UPDATE: Es ist, weil [diese Antwort] (https://stackoverflow.com/a/942592/114558) die gleiche Lösung bietet aber mit mehr Info. – rinogo

0

Standard-SQL Verweise auf Spaltenaliasnamen in einer WHERE-Klausel nicht zulässt. Diese Einschränkung wird auferlegt, da bei der Auswertung der WHERE-Klausel der Spaltenwert möglicherweise noch nicht ermittelt wurde. Die folgende Abfrage ist beispielsweise unzulässig:

SELECT-ID, COUNT (*) AS cnt FROM Tablenname WHERE Cnt> 0 GROUP BY ID;

Verwandte Themen