2010-12-28 7 views
0

In meiner Datenbank berechne ich Abstand zwischen den Knoten mit:Kann ich in einer MySQL SELECT-Abfrage meine "AS-Spalte" in einer WHERE-Spezifikation verwenden?

SELECT DISTINCT 
     dest.name, 
     AsText(orig.location), 
     AsText(dest.location), 
     round((glength(linestringfromwkb(linestring((orig.location), (dest.location)))))) as distance 
FROM nodes orig, 
    nodes dest 
WHERE orig.name='GERP' 

Ich würde

and distance < dest.visibility 

am Ende hinzufügen will, aber dieser Abstand ist eine unbekannte Spalte sagte mir.

Jeder Einblick sehr geschätzt.

+0

Sie könnten den Alias ​​in einer HAVING-Klausel verwenden, aber das wäre für ein Feld wie dieses mit einem hohen Rechenaufwand sehr ineffizient. –

Antwort

0

Verwendung:

SELECT DISTINCT 
     dest.name, 
     AsText(orig.location), 
     AsText(dest.location), 
     round((glength(linestringfromwkb(linestring((orig.location), (dest.location)))))) as distance 
    FROM nodes orig, 
     nodes dest 
WHERE orig.name = 'GERP' 
    AND round((glength(linestringfromwkb(linestring((orig.location), (dest.location)))))) < dest.visibility 

SQL erlaubt es nicht, Spaltenaliasnamen in der WHERE-Klausel Zugriff - die früheste MySQL unterstützt die GROUP BY Klausel ist.

Auch Ihre Abfrage enthält keine Kriterien zum Verknüpfen der beiden Tabelleninstanzen - was zu einem kartesischen Produkt führt.

+0

Danke - das ist es, womit ich gehe! –

1

Nein, aber Sie können

and dest.visibility > round((glength(linestringfromwkb(linestring((orig.location), (dest.location)))))) 

mysql hinzufügen sollten intelligent genug sein, um nur den Ausdruck einmal zu berechnen.

0

Sie können den berechneten Spaltennamen des Ergebnissatzes nicht in der where-Klausel verwenden.

Sie müssen (leider) wieder verwenden den gesamten Ausdruck Sie verwendet es zu berechnen

and round((glength(linestringfromwkb(linestring((orig.location), (dest.location)))))) 
    < dest.visibility 

Es gibt zwei Workarounds:

  1. Wenn Sie den Text der Abfrage erstellen Außerhalb von SQL (z. B. von Perl, PHP usw.) können Sie den Ausdruck vor der Abfrage in einer Zeichenfolge speichern und die Zeichenfolge erneut verwenden:

    $long_expr = "round((glength(linestringfromwkb(linestring((orig.location), (dest.location))))))"; 
    $sql = qq[SELECT DISTINCT 
    

    dest.name, AsText (orig.location), AsText (dest.location), $ long_expr als Abstand ... und $ long_expr < dest.visibility

  2. Speichern Sie die ursprüngliche Abfrage (ohne die letzte AND) in einer temporären Tabelle (aber visibility Spalte in der Auswahl) inlcude, und dann eine Unterabfrage des folgenden

    SELECT * from #temp_table 
    WHERE distance < visibility 
    
  3. wie # 2, aber statt temporärer Tabelle, tun.

1

HAVING ist dein Freund.

Ein select_expr kann einen Alias ​​ mit AS alias_name erhalten. Der Alias ​​wird als Spaltenname des Ausdrucks verwendet und kann in GROUP BY, ORDER BY oder HAVING-Klauseln verwendet werden.

Um sowohl Standard-SQL und das MySQL-spezifische Verhalten des Seins der Lage zu beziehen Spalten in der SELECT Liste, MySQL 5.0.2 und höher erlauben, DIE aufnehmen zu Spalten in der SELECT Liste, Spalten beziehen sich in die GROUP BY-Klausel, Spalten in äußeren Unterabfragen und Aggregatfunktionen.

Beachten Sie, dass HAVING nicht optimiert werden kann und langsam sein wird. Kein neues Problem mit Ihrer Abfrage, aber ...

+0

"Kein neues Problem mit Ihrer Anfrage, aber ...". Liebe es ;-) +1 –

+0

Die HAVING-Klausel ist für Aggregatnutzung, nicht auf MySQL-Funktionalität, die wenige, wenn andere Datenbanken unterstützen. –

+0

natürlich ist es MySQL-spezifisch leid, wenn das nicht klar genug war. Die Frage bezieht sich auch auf MysQL und damit auch auf die Frage. – chx

2

Verwenden Sie eine Unterabfrage, dann müssen Sie nur die Formel einmal eingeben (und wenn Sie es ändern müssen, müssen Sie nur einmal ändern).

+0

Die Unterabfrage ist nicht erforderlich - dieser Ansatz riskiert zwei Übergänge über die Tabelle, was die Leistung nicht verbessert. –

Verwandte Themen