sql >> Base de Datos >  >> RDS >> Sqlserver

Alias ​​de referencia (calculado en SELECT) en la cláusula WHERE

No puede hacer referencia a un alias excepto en ORDER BY porque SELECT es la penú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 simplemente repite 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 debería considerar una columna calculada (y tal vez persistente), especialmente si muchas consultas se refieren a esta misma expresión.

PD:tus temores parecen infundados. Al menos en este ejemplo simple, SQL Server es lo suficientemente inteligente como para realizar el cálculo solo una vez, aunque haya hecho referencia a él dos veces. Continúe y compare los planes; Verás que son idénticos. Si tiene un caso más complejo en el que ve la expresión evaluada varias veces, publique la consulta más compleja y los planes.

Aquí hay 5 consultas de ejemplo que arrojan 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 las cinco consultas: