次の例を考えてみます。
DECLARE @suppliedNumber MONEY
SET @suppliedNumber = 245656.00
SELECT
ah.FirstName,
ah.LastName
FROM
AccountHolders AS ah
JOIN
[dbo].[Accounts] AS a
ON
ah.Id = a.AccountHolderId
GROUP BY
ah.FirstName, ah.LastName
HAVING SUM(a.Balance) > @suppliedNumber
ご覧のとおり、クエリにはどのような順序もありません。しかし、実行プランを見ると、暗黙的なソートが見られます。
なぜこうなった?これの背後にある技術的な理由は何ですか?
Microsoft SQL Server 2014(RTM-CU14)(KB3158271)-12.0.2569.0(X64)2016年5月27日15:06:08 Copyright(c)Microsoft Corporation Express Edition(64-bit)on Windows NT 6.3(Build 14393:)
@sp_BlitzErikがコメントで述べたように、 ストリーム集計演算子 では、入力をソートする必要があります。
ストリーム集約演算子は、1つ以上の列で行をグループ化し、クエリから返された1つ以上の集約式を計算します。この演算子の出力は、クエリの後の演算子によって参照されるか、クライアントに返されるか、またはその両方です。 Stream Aggregateオペレーターは、グループ内の列で順序付けられた入力を必要とします。前のソート演算子または順序付けされたインデックスシークまたはスキャンのためにデータがまだソートされていない場合、オプティマイザはこの演算子の前にソート演算子を使用します。 SHOWPLAN_ALLステートメントまたはSQL Server Management Studioのグラフィカル実行プランでは、GROUP BY述語の列がArgument列にリストされ、集計式がDefined Values列にリストされます。
FirstName, LastName
にインデックスを追加すると、並べ替えがなくなる場合があります(クエリオプティマイザーがインデックスを使用する場合)。
join
がソートを生成しているとは思いません
group by
sum
がソートを生成しています
クエリプランでの順序を確認する
これはもっと速いかもしれません
目的が同じ名前の複数のアカウントである場合は機能しません
SELECT ah.Id, ah.FirstName, ah.LastName
FROM
AccountHolders AS ah
JOIN
[dbo].[Accounts] AS a
ON
ah.Id = a.AccountHolderId
GROUP BY
ah.Id, ah.FirstName, ah.LastName
HAVING SUM(a.Balance) > @suppliedNumber
または
SELECT ah.Id, ah.FirstName, ah.LastName
FROM AccountHolders AS ah
JOIN ( select AccountHolderId
from [dbo].[Accounts] A
GROUP BY Id
HAVING SUM(Balance) > @suppliedNumber
) a
on a.AccountHolderId = ah.ID