必要なすべてのデータを取得しなくなったクエリを書き換えているところです。私の質問は、私が今まで見たことのないプラクティスに関するもので、StackExchangeでこの問題に特に対処する質問を見つけていません。
HAVING
が個々の行に条件を導入するのと同じように、WHERE
ステートメントの目的は集計に条件を導入することです。ただし、このコードでは、集約を使用したクエリでHAVING
の代わりにWHERE
が使用されています。 HAVING
の条件は、集計に対してではなく、非集計列に適用されます。
例えば:
SELECT id, filedate, SUM(amount)
FROM Sales
GROUP BY id, filedate
HAVING id = 123 AND filedate = '1/1/2018'
とは対照的に:
SELECT id, filedate, SUM(amount)
FROM Sales
WHERE id = 123 AND filedate = '1/1/2018'
GROUP BY id, filedate
この戦略には、パフォーマンスへの影響やその他の利点/欠点がありますか?
私は診断を自分で実行しようとしたことはありません。優先順位ではありません。自分の時間に実行する必要があります。しかし、これについて明確な答えがなければ、私はそう思うかもしれません。
私の懸念は、オプティマイザがこのクエリをどのように表示するかです。すべてのデータを集計し、HAVING
句に基づいて結果セットを制限しますか、または非集計列を具体的に参照しているため、個々の行に所持条件を適用できることを認識していますか?
編集:私のサンプルクエリと書き換えている実際のSQLの場合、プランは同じですが、クエリは同様の複雑さであり、同じプランから結論を導き出すにはまだ十分な知識がありません。
HAVING
の条件は、集計に対してではなく、非集計列に適用されます。
ここでの問題は、HAVING
句が何に適用されるかをどのように説明しているかにあります。 HAVING
句alwaysはaggregatedフィールドに適用され、これは、残りのすべての列post-aggregationです。 HAVING
句が集計関数に適用されていないことを示したり、伝えたりしようとしています。 。しかし実際には、HAVING
句がその集約関数の結果、または最初の例ではグループ化列の結果を管理します。ただし、どちらの場合も、集計はすでに実行されています。
したがって、パフォーマンスの観点から(後でこのコードを更新しようとする他の人にとって読みやすさは言うまでもありません)、WHERE
句を使用してが何になるかをフィルターで絞り込みます集約し、次にHAVING
句を使用して、が集約されたものを除外します。そして、質問に示されている単純なテストの結果は、2つのタイミング(またはクエリが処理されるシーケンス内の論理配置)のタイミングの違いを覆い、同じことを「実行」しているように見えますが、行の束を集約して、後でそれらを論理的に削除して破棄することができる場合にのみ、それらを破棄するのが効率的でなかったら、私はかなり驚きます。ただし、これらの実行例がこの単純な例で類似していることがわかった場合、これらのHAVING
条件を実際のWHERE
条件は、実行前にクエリを書き換えます。しかし、その場合でも、このような方法でクエリを作成しないことをお勧めします。それは、オプティマイザがより効率的な計画を見つけるためにその時間/ CPUサイクルを費やす必要があるときに、不正なコードを書き換えるのに余分な時間をかけるためです。 @ DavidSpillett 追加(この回答のコメント内):「さらに、クエリプランナーが最適化の可能性を確認しているため、より複雑なクエリではないか、コードが移植された場合別のデータベース(またはSQL Serverの古いバージョンのみ)」.
その価値については、Microsoft HAVING句のドキュメント でも、GROUP BY
が存在しない場合はWHERE
句として機能すると述べています。ドキュメントがGitHubにあるので、最近 プルリクエスト#235:HAVING句を修正して改善する で修正できました。
ソロモンは非常に良い説明をしますが、私にとって、簡単な答えは、Itzik Ben-Ganが書いたSQLクエリの論理処理順序を覚えておくことです here シーケンスは常に
FROM-> WHERE-> GROUP BY-> HAVING-> SELECT-> ORDER BY
つまり、GROUP BYの前にWHEREフィルターを適用できる場合、GROUP BYによって処理されるデータの量を減らすことができます。適切なインデックスが存在する場合、WHERE操作は非常に効率的です。そのため、WHEREを使用してHAVINGがビジネスの観点から同じ結果を返す場合、WHEREは常にHAVINGよりも優れています。