Вы не можете ссылаться на псевдоним, кроме ORDER BY, потому что SELECT - это второе последнее вычисляемое предложение. Два обходных пути:
SELECT BalanceDue FROM (
SELECT (InvoiceTotal - PaymentTotal - CreditTotal) AS BalanceDue
FROM Invoices
) AS x
WHERE BalanceDue > 0;
Или просто повторите выражение:
SELECT (InvoiceTotal - PaymentTotal - CreditTotal) AS BalanceDue
FROM Invoices
WHERE (InvoiceTotal - PaymentTotal - CreditTotal) > 0;
Я предпочитаю последнее. Если выражение чрезвычайно сложное (или требует больших затрат для вычисления), вам, вероятно, следует вместо этого рассмотреть вычисляемый столбец (и, возможно, постоянный), особенно если много запросов относятся к этому же выражению.
PS ваши опасения кажутся беспочвенными. По крайней мере, в этом простом примере SQL Server достаточно умен, чтобы выполнить вычисление только один раз, даже если вы дважды ссылались на него. Идите и сравните планы; вы увидите, что они идентичны. Если у вас более сложный случай, когда вы видите, что выражение оценивается несколько раз, опубликуйте более сложный запрос и планы.
Вот 5 примеров запросов, каждый из которых дает один и тот же план выполнения:
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;
Итоговый план по всем пяти запросам: