申し訳ありませんが、ある種のサブクエリなしでこれを行う実際の方法はありません。あなたが書いたクエリは問題ありません。私の意見では、探しているものを達成するための最良の構文は次のとおりです。
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 APPLYOUTER 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 APPLYTOP
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, IDIDTest