申し訳ありませんが、ある種のサブクエリなしでこれを行う実際の方法はありません。あなたが書いたクエリは問題ありません。私の意見では、探しているものを達成するための最良の構文は次のとおりです。
SELECT
T.ID,
HT.*
FROM
dbo.Test T
OUTER APPLY (
SELECT TOP 1 *
FROM dbo.TestHistory HT
WHERE T.ID = HT.TestID
ORDER BY HT.ID DESC
) HT
;
SQL Fiddle でこれを試してみてください。
Test
一致する行を持つ行のみが表示されるように制限する場合は、代わりに をTestHistory
使用します。CROSS APPLY
OUTER APPLY
また、このようなクエリは可能であり、理解しやすいかもしれませんが、パフォーマンスが低下する可能性が高く、さらにTestHistory
各行に少なくとも 1 つの行が必要Test
です。
SELECT
T.ID,
HT.*
FROM
dbo.Test T
INNER JOIN dbo.TestHistory HT
ON T.ID = HT.TestID
WHERE
HT.ID = (
SELECT Max(HT2.ID)
FROM dbo.TestHistory HT2
WHERE T.ID = HT2.TestID
)
;
ソリューションを使用することもできますが、それが利用可能な場合、それはとRow_Number()
同じように機能しないことが多いため、私はそれから遠ざかる傾向があります.CROSS APPLY
TOP
SELECT
T.ID,
HT.TestID,
HT.Price
FROM
dbo.Test T
LEFT JOIN (
SELECT
Selector = Row_Number() OVER (
PARTITION BY HT.TestID ORDER BY HT.ID DESC
),
*
FROM dbo.TestHistory HT
) HT
ON T.ID = HT.TestID
AND HT.Selector = 1
;
SQL Fiddle でこれを試してみてください。
TOP 1
そのソリューションまたはソリューションのパフォーマンスが優れているかどうかを確認する唯一の方法Row_Number()
は、適切に代表的な多数のデータを使用して、データベース内の各ソリューションを試すことです。履歴エントリがほとんどなく、メイン エントリが非常に多い場合は、 を使用するとより良い結果が得られる可能性Row_Number()
があります。ただし、メイン エントリごとに多数の履歴エントリがある場合は、このTOP
方法が最適なパフォーマンスを発揮する可能性があります。
テーブルのインデックスも大きな違いを生む可能性があります。適切なテーブル アクセスを許可する適切なインデックスがあることを確認します (たとえば、PK が on であっても、テーブルのクラスター化インデックスは on にTestHistory
する必要があります)。毎回テーブル全体をクエリする場合、インデックスはそれほど重要ではないかもしれませんが、行のセットを制限する条件が発生した瞬間に、インデックスは非常に重要になります。TestID, ID
ID
Test