最初の違いは、このFROM
句が結果の最初のカーディナリティを管理することです。
あなたの場合、結果はアルバムの行ごとに1行になります。SELECT
句のスカラーサブクエリはこれを変更できません。サブクエリがたまたま複数の行を返す場合、SQLServerは例外をスローします。結果に追加されることはありません。
この論理結合をFROM
句に移動すると、最初のカーディナリティが再定義されます。アルバムの行ごとに1行ではなく、Album LEFT OUTER JOIN AblumPictures ON...
などの行ごとに1行になります。アルバムの行ごとに複数の行が生成される場合、SQLServerは副選択の場合のように例外をスローしません。むしろ、結果に行を追加します。
したがって、この点で、サブクエリは意図を表現するためのより良い仕事をし、その意図に違反するデータからあなたを積極的に保護するより良い仕事をします:「アルバムごとに1行を与え、アルバムごとに、ここのURL、ネストされたIDを含めますそこから」など。
ただし、機能的に言えば、大きな欠点があります。スカラーサブクエリはタプル全体を返すことができません。サブクエリを作成するためにこのすべての作業を実行し、SQL Serverがそれを実行するためにこのすべての作業を実行しました。これで、この1つのスカラー戻り値に制限されます。それで問題ない場合もありますが、さらに必要な場合もあります。さらに必要な場合は、FROM
句が必要です。
FROM
スカラーサブクエリに相当する最も近い句はOUTER JOIN
ではなく、不思議なOUTER APPLY
です。OUTER APPLY
はスカラー式ではありません。タプル全体と任意の数の行を返します。
最初の近似:
SELECT Albums.*, AlbumPictures.URL, NestedAlbums.AlbumID
FROM Albums
OUTER APPLY (
SELECT TOP (1) * FROM AlbumPictures
WHERE (AlbumID = Albums.AlbumID) AND (AlbumCover = 'True')
) AlbumPictures
OUTER APPLY (
SELECT TOP (1) * FROM NestedAlbums
WHERE (AlbumID = Albums.AlbumID)
) NestedAlbums
WHERE Albums.AlbumID IN (SELECT StringVal FROM funcListToTableInt(@whereAlbumID))
したがって、のおかげでTOP (1)
、アルバムは依然として結果の最初のカーディナリティを支配します。ただし、関連するテーブルのすべての列にアクセスできるようになりました。これはすばらしいことです。
次に、それが必要ではないと確信している場合(キーとインデックスにより、サブクエリは1行しか返すことができない)、より単純な形式を使用して書き直すことができます。TOP (1)
SELECT Albums.*, AlbumPictures.URL, NestedAlbums.AlbumID
FROM Albums
OUTER APPLY (
SELECT * FROM AlbumPictures
WHERE (AlbumID = Albums.AlbumID) AND (AlbumCover = 'True')
) AlbumPictures
OUTER APPLY (
SELECT * FROM NestedAlbums
WHERE (AlbumID = Albums.AlbumID)
) NestedAlbums
WHERE Albums.AlbumID IN (SELECT StringVal FROM funcListToTableInt(@whereAlbumID))
これは論理的に次と同等OUTER JOIN
です:
SELECT Albums.*, AlbumPictures.URL, NestedAlbums.AlbumID
FROM Albums
LEFT OUTER JOIN AlbumPictures
ON AlbumPictures.AlbumID = Albums.AlbumID
AND AlbumPictures.AlbumCover = 'True'
LEFT OUTER JOIN NestedAlbums
ON NestedAlbums.AlbumID = Albums.AlbumID
WHERE Albums.AlbumID IN (SELECT StringVal FROM funcListToTableInt(@whereAlbumID))
そして、あなたはそれを持っています。どちらが良いですか?さて、あなたが何をするにしても、それを単純にしてください。
パフォーマンスワイズ、一般的に、フォーム間に大きな違いはありません。特定のテーブルとインデックスの実行プランを並べて比較できます。SQLServerが論理的に同等のクエリをどのように書き換えるかを確認することは良い学習経験です。OUTER APPLY
(w / o TOP (1)
)と。については同じ計画が見られると思いLEFT OUTER JOIN
ます。