Nie możesz odwoływać się do aliasu, z wyjątkiem ORDER BY, ponieważ SELECT jest przedostatnią klauzulą, która jest oceniana. Dwa obejścia:
SELECT BalanceDue FROM (
SELECT (InvoiceTotal - PaymentTotal - CreditTotal) AS BalanceDue
FROM Invoices
) AS x
WHERE BalanceDue > 0;
Lub po prostu powtórz wyrażenie:
SELECT (InvoiceTotal - PaymentTotal - CreditTotal) AS BalanceDue
FROM Invoices
WHERE (InvoiceTotal - PaymentTotal - CreditTotal) > 0;
Wolę to drugie. Jeśli wyrażenie jest niezwykle złożone (lub kosztowne w obliczeniu), prawdopodobnie powinieneś rozważyć zamiast tego kolumnę obliczaną (i być może utrwaloną), zwłaszcza jeśli wiele zapytań odnosi się do tego samego wyrażenia.
PS Twoje obawy wydają się bezpodstawne. Przynajmniej w tym prostym przykładzie SQL Server jest na tyle inteligentny, że wykonuje obliczenia tylko raz, nawet jeśli odwołałeś się do niego dwukrotnie. Śmiało i porównaj plany; zobaczysz, że są identyczne. Jeśli masz bardziej złożony przypadek, w którym wyrażenie zostało ocenione wielokrotnie, opublikuj bardziej złożone zapytanie i plany.
Oto 5 przykładowych zapytań, które dają dokładnie ten sam plan wykonania:
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;
Wynikowy plan dla wszystkich pięciu zapytań: