Du kan ikke referere til et alias undtagen i ORDER BY, fordi SELECT er den næstsidste klausul, der evalueres. To løsninger:
SELECT BalanceDue FROM (
SELECT (InvoiceTotal - PaymentTotal - CreditTotal) AS BalanceDue
FROM Invoices
) AS x
WHERE BalanceDue > 0;
Eller bare gentag udtrykket:
SELECT (InvoiceTotal - PaymentTotal - CreditTotal) AS BalanceDue
FROM Invoices
WHERE (InvoiceTotal - PaymentTotal - CreditTotal) > 0;
Jeg foretrækker det sidste. Hvis udtrykket er ekstremt komplekst (eller dyrt at beregne), bør du nok overveje en beregnet kolonne (og måske vedvarede) i stedet, især hvis mange forespørgsler refererer til det samme udtryk.
PS din frygt virker ubegrundet. I det mindste i dette simple eksempel er SQL Server smart nok til kun at udføre beregningen én gang, selvom du har henvist til den to gange. Gå videre og sammenlign planerne; du vil se, at de er identiske. Hvis du har en mere kompleks sag, hvor du ser udtrykket evalueret flere gange, bedes du sende den mere komplekse forespørgsel og planerne.
Her er 5 eksempler på forespørgsler, der alle giver nøjagtig den samme eksekveringsplan:
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;
Resulterende plan for alle fem forespørgsler: