Sie können auf einen Alias nur in ORDER BY verweisen, da SELECT die zweitletzte Klausel ist, die ausgewertet wird. Zwei Abhilfen:
SELECT BalanceDue FROM (
SELECT (InvoiceTotal - PaymentTotal - CreditTotal) AS BalanceDue
FROM Invoices
) AS x
WHERE BalanceDue > 0;
Oder einfach wiederholen Sie den Ausdruck:
SELECT (InvoiceTotal - PaymentTotal - CreditTotal) AS BalanceDue
FROM Invoices
WHERE (InvoiceTotal - PaymentTotal - CreditTotal) > 0;
Ich ziehe das letztere. Wenn der Ausdruck extrem komplex (oder kostspielig in der Berechnung) ist, sollten Sie stattdessen eine berechnete Spalte (und möglicherweise beibehalten) in Betracht ziehen, insbesondere dann, wenn sich viele Abfragen auf denselben Ausdruck beziehen.
PS Ihre Ängste scheinen unbegründet. In diesem einfachen Beispiel ist SQL Server intelligent genug, um die Berechnung nur einmal durchzuführen, obwohl Sie sie zweimal referenziert haben. Gehen Sie voran und vergleichen Sie die Pläne; Sie werden sehen, dass sie identisch sind. Wenn Sie einen komplexeren Fall haben, in dem der Ausdruck mehrfach ausgewertet wird, buchen Sie bitte die komplexere Abfrage und die Pläne.
Hier sind 5 Beispiel fragt, dass alle exakt die gleichen Ausführungsplan ergeben:
SELECT LEN(name) + column_id AS x
FROM sys.all_columns
WHERE LEN(name) + column_id > 30;
SELECT x FROM (
SELECT LEN(name) + column_id AS x
FROM sys.all_columns
) AS x
WHERE x > 30;
SELECT LEN(name) + column_id AS x
FROM sys.all_columns
WHERE column_id + LEN(name) > 30;
SELECT name, column_id, x FROM (
SELECT name, column_id, LEN(name) + column_id AS x
FROM sys.all_columns
) AS x
WHERE x > 30;
SELECT name, column_id, x FROM (
SELECT name, column_id, LEN(name) + column_id AS x
FROM sys.all_columns
) AS x
WHERE LEN(name) + column_id > 30;
Resultierende Plan für alle fünf Anfragen:
vielen Dank Aaron! –
Wow. SQL Server ist schlau genug, um die Berechnung nur einmal durchzuführen – alternatefaraz
Wow, das ist eine sehr hochwertige Antwort! – Siddhartha