Bạn không thể tham chiếu một bí danh ngoại trừ trong ORDER BY vì SELECT là mệnh đề cuối cùng thứ hai được đánh giá. Hai cách giải quyết:
SELECT BalanceDue FROM (
SELECT (InvoiceTotal - PaymentTotal - CreditTotal) AS BalanceDue
FROM Invoices
) AS x
WHERE BalanceDue > 0;
Hoặc chỉ cần lặp lại biểu thức:
SELECT (InvoiceTotal - PaymentTotal - CreditTotal) AS BalanceDue
FROM Invoices
WHERE (InvoiceTotal - PaymentTotal - CreditTotal) > 0;
Tôi thích cái sau. Nếu biểu thức cực kỳ phức tạp (hoặc tốn kém để tính toán), có lẽ bạn nên xem xét một cột được tính toán (và có lẽ vẫn tồn tại), đặc biệt nếu rất nhiều truy vấn đề cập đến cùng biểu thức này.
PS nỗi sợ hãi của bạn dường như vô căn cứ. Trong ví dụ đơn giản này, ít nhất, SQL Server đủ thông minh để chỉ thực hiện phép tính một lần, mặc dù bạn đã tham chiếu nó hai lần. Đi trước và so sánh các kế hoạch; bạn sẽ thấy chúng giống hệt nhau. Nếu bạn có một trường hợp phức tạp hơn khi bạn thấy biểu thức được đánh giá nhiều lần, vui lòng gửi truy vấn phức tạp hơn và các kế hoạch.
Dưới đây là 5 truy vấn mẫu mà tất cả đều mang lại cùng một kế hoạch thực hiệ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;
Kế hoạch kết quả cho tất cả năm truy vấn: