No puede hacer referencia a un alias excepto en ORDER BY porque SELECT es la segunda última cláusula que se evalúa. Dos soluciones:
SELECT BalanceDue FROM (
SELECT (InvoiceTotal - PaymentTotal - CreditTotal) AS BalanceDue
FROM Invoices
) AS x
WHERE BalanceDue > 0;
O sólo tiene que repetir la expresión:
SELECT (InvoiceTotal - PaymentTotal - CreditTotal) AS BalanceDue
FROM Invoices
WHERE (InvoiceTotal - PaymentTotal - CreditTotal) > 0;
prefiero este último. Si la expresión es extremadamente compleja (o costosa de calcular), probablemente deba considerar una columna calculada (y tal vez persistente), especialmente si muchas consultas se refieren a esta misma expresión.
PS sus temores parecen infundados. En este sencillo ejemplo al menos, SQL Server es lo suficientemente inteligente como para realizar el cálculo una sola vez, aunque lo hayas hecho dos veces. Adelante y compara los planes; verás que son idénticos. Si tiene un caso más complejo en el que vea la expresión evaluada varias veces, publique la consulta más compleja y los planes.
Aquí hay 5 consultas de ejemplo que todos conseguirán exactamente el mismo plan de ejecución:
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;
plan resultante para los cinco consultas:
muchas gracias Aaron! –
Wow. SQL Server es lo suficientemente inteligente como para realizar solo el cálculo una vez – alternatefaraz
¡Vaya, esta es una respuesta de muy alta calidad! – Siddhartha