153
SELECT (InvoiceTotal - PaymentTotal - CreditTotal) AS BalanceDue
FROM Invoices
WHERE BalanceDue > 0 --error

選択された列のリストで変数として設定された計算値は、句BalanceDueでは使用できません。WHERE

それができる方法はありますか?この関連する質問 ( Using a variable in MySQL Select Statment in a Where Clause ) では、答えは、実際には、いいえ、計算を書き出す (そしてクエリでその計算を実行する) だけで、2 回ではないようです。これは満足です。

4

4 に答える 4

270

SELECT は最後から 2 番目に評価される句であるため、ORDER BY 以外ではエイリアスを参照できません。2 つの回避策:

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 は計算を 2 回参照したとしても、計算を 1 回しか実行しないほどスマートです。先に進み、計画を比較してください。それらが同一であることがわかります。式が複数回評価されるより複雑なケースがある場合は、より複雑なクエリと計画を投稿してください。

すべてがまったく同じ実行計画を生成する 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;

5 つのクエリすべての結果のプラン:

ここに画像の説明を入力

于 2012-06-25T00:54:29.927 に答える