これは、3つのアプローチを示す非常に小さなサンプルデータを使用したテスト例です。
最適なクエリプランを取得するには:
People by(GroupID、EntryDate)に一意でないインデックスを付けます。
A.元の擬似コード(注文は行いますが日付は表示されません)を使用するか、
B.上位1つのサブクエリを使用して、日付を取得して表示します。
AとBのクエリプランは同じです。
Peopleテーブルへの左結合とmax()を使用すると、インデックス内の単一の行をプローブするのではなく、スキャン(GroupID内で最大)が最大値を取得します。
set nocount on
if object_id('Groups') is not null drop table Groups
if object_id('People') is not null drop table People
go
-- set up tables
create table Groups
(
ID int primary key,
Name varchar(20)
)
create table People
(
ID int,
GroupID int,
EntryDate datetime
)
-- make an index that is ordered by Group, EntryDate
create index IE_GroupDate on People(GroupID, EntryDate)
-- Sample data
insert into Groups (ID, Name)
values
(1, 'Group1'),
(2, 'Group2'),
(3, 'GroupC')
insert into People (ID, GroupID, EntryDate)
values
(1, 1, '2012-01-01'),
(2, 1, '2012-02-01'),
(1, 3, '2007-12-31')
-- Queries
-- Equivalent to the original poster's intent. Note that it doesn't actually
-- show the entry date
select *
from Groups G
order by (
select top 1 EntryDate
from People P
where P.GroupID = G.ID order by EntryDate desc)
-- Same query (by query plan) but includes the EntryDate in the result set
select
G.ID,
G.Name,
LatestEntryDate = Latest.EntryDate
from Groups G
outer apply (
select top 1 EntryDate
from People P
where P.GroupID = G.ID
order by EntryDate desc
) Latest
order by LatestEntryDate
-- Query using left join. This causes a scan of the left join table to
-- compute the max. (The optimizer isn't smart enough to turn this into
-- a TOP 1)
select
G.ID,
G.Name,
LatestEntryDate = max(P.EntryDate)
from Groups G
left join People P on P.GroupID = G.ID
group by G.ID, G.Name
order by max(P.EntryDate)