Sqlserver
 sql >> Base de Dados >  >> RDS >> Sqlserver

Alias ​​de referência (calculado em SELECT) na cláusula WHERE


Você não pode fazer referência a um alias exceto em ORDER BY porque SELECT é a penúltima cláusula avaliada. Duas soluções alternativas:
SELECT BalanceDue FROM (
  SELECT (InvoiceTotal - PaymentTotal - CreditTotal) AS BalanceDue
  FROM Invoices
) AS x
WHERE BalanceDue > 0;

Ou apenas repita a expressão:
SELECT (InvoiceTotal - PaymentTotal - CreditTotal) AS BalanceDue
FROM Invoices
WHERE  (InvoiceTotal - PaymentTotal - CreditTotal)  > 0;

Eu prefiro o último. Se a expressão for extremamente complexa (ou cara para calcular), você provavelmente deve considerar uma coluna computada (e talvez persistente), especialmente se muitas consultas se referirem a essa mesma expressão.

PS seus medos parecem infundados. Neste exemplo simples, pelo menos, o SQL Server é inteligente o suficiente para realizar o cálculo apenas uma vez, mesmo que você o tenha referenciado duas vezes. Vá em frente e compare os planos; você verá que eles são idênticos. Se você tiver um caso mais complexo em que vê a expressão avaliada várias vezes, poste a consulta mais complexa e os planos.

Aqui estão cinco exemplos de consultas que geram exatamente o mesmo plano de execução:
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;

Plano resultante para todas as cinco consultas: