Я знаю, что этот вопрос старше, но есть другой подход, который, как мне кажется, недостаточно используется:
Вы можете объединять таблицы обратно в себя и использовать оператор для поиска «самой последней» записи.
Ответ
SELECT CP.CarePlanId, R.ReferralId, R.ReferralDate
FROM CarePlan CP
LEFT OUTER JOIN Referral R ON R.CarePlanId = CP.CarePlanId
LEFT OUTER JOIN Referral R_NEWER ON R.CarePlanId = R_NEWER.CarePlanId AND R.ReferralDate < R_NEWER.ReferralDate
WHERE R_NEWER.ReferralId IS NULL
Результаты:
CP.CarePlanId R.ReferralId R.ReferralDate
---------- ---------- ------------
1 1 05/15/12
2 NULL NULL
Объяснение
Давайте разберемся с этим. По сути, вы говорите, что для каждой записи реферала (слева) присоединяются к каждой другой записи реферала, которая связана с тем же CarePlanId, но ТОЛЬКО там, где имеется более новая ReferralDate.
Вот запрос без предложения where (вместе с дополнительной информацией из таблицы R_NEWER):
SELECT CP.CarePlanId, R.ReferralId, R.ReferralDate, R_NEWER.ReferralId, R.NEWER.ReferralDate
FROM CarePlan CP
LEFT OUTER JOIN Referral R ON R.CarePlanId = CP.CarePlanId
LEFT OUTER JOIN Referral R_NEWER ON R.CarePlanId = R_NEWER.CarePlanId AND R.ReferralDate < R_NEWER.ReferralDate
Вот результат этого запроса:
CP.CarePlanId R.ReferralId R.ReferralDate R_NEWER.ReferralId R_NEWER.ReferralDate
---------- ---------- ------------ ------------ ------------
1 1 05/15/12 NULL NULL
2 NULL NULL NULL NULL
1 2 05/10/12 1 05/15/12
Как видите, только реферальный Id 2 (3-я запись выше) нашел "более новую" запись для присоединения в реферальной таблице (т.е. реферальный Id 1). Идентификатор реферала 1 (1-я запись выше) НЕ нашел «более нового» реферала (для того же CarePlanId).
Итак, имея это в виду, теперь мы просто добавляем обратно выражение where:
SELECT CP.CarePlanId, R.ReferralId, R.ReferralDate, R_NEWER.ReferralId, R.NEWER.ReferralDate
FROM CarePlan CP
LEFT OUTER JOIN Referral R ON R.CarePlanId = CP.CarePlanId
LEFT OUTER JOIN Referral R_NEWER ON R.CarePlanId = R_NEWER.CarePlanId AND R.ReferralDate < R_NEWER.ReferralDate
WHERE R_NEWER.ReferralId IS NULL
и получите:
CP.CarePlanId R.ReferralId R.ReferralDate R_NEWER.ReferralId R_NEWER.ReferralDate
---------- ---------- ------------ ------------ ------------
1 1 05/15/12 NULL NULL
2 NULL NULL NULL NULL
На этом этапе просто удалите столбцы R_NEWER из вашего SELECT, так как они больше не нужны, и у вас есть ответ.
Важно помнить, что «где» применяется ПОСЛЕ того, как объединения произошли, но оператор ON происходит во время соединения. Чтобы сделать это более понятным для меня, я всегда стараюсь писать SELECTs и JOINs и возвращать столбцы из каждой таблицы, к которой я присоединяюсь, а затем добавлять свои предложения WHERE, когда у меня есть четкое представление о том, что возвращается.
Протест
Этот подход прекрасно работает в большинстве случаев, но возможно иметь дублирующиеся строки, если у вас было 2 реферала (для одного и того же CarePlanId) с датой 15.05.12, и эта дата была «самой последней». Чтобы обойти это, вы можете расширить ваши объединения (ы) до ограничения, основанного на «самом высоком» ReferralId, если возникает такой сценарий.