我基本上需要在2个表上进行左外连接(CarePlan和Referrals)问题是我需要最新的推荐如果它存在,如果它不存在则没问题。
我有这两个查询 1.加入CarePlan / Referral表 - 如果护理计划有多个推荐,或者根本没有推荐信息(左外连接),则创建重复的护理计划 2.根据CarePlanId
选择基于日期的前1个推荐我想结合这两个所以我抓住所有的护理计划和它的推荐,如果它存在,如果它 - 只采取最新的推荐
select * from CarePlan c //query 1
left outer join Referral r on
r.CarePlanId = c.CarePlanId
select top 1 * from Referral r //query 2
where r.CarePlanId = '1'
order by ReferralDate desc
编辑:
第一个查询给我这样的东西:
CarePlanID ReferralId ReferralDate
---------- ---------- ------------
1 1 05/15/12
2 NULL NULL
1 2 05/10/12 //Old date, dont want this careplan
第二个查询将为我提供最新日期的推荐
ReferralId ReferralDate
---------- ------------
1 05/15/12
推荐数据,可能有0个或更多属于Careplan的推荐
ReferralID CarePlanId Date
---------- ---------- ----
1 1 05/15/12
2 1 05/10/12
最终我想要一个查询,为我提供具有最新日期的推荐的careplans,如果它没有它,则为引用无效
像这样:CarePlanId ReferralId ReferralDate
---------- ---------- ------------
1 1 05/15/12
2 NULL NULL
谢谢 - 我希望这是有道理的
答案 0 :(得分:43)
select *
from CarePlan c
outer apply (
select top 1 * --top N rows
from Referral r
where r.CarePlanId = c.CarePlanId --join condition
order by /*fill this in!*/
) x
请注意,由于优化程序漏洞(包括2014版本),这会强制进行循环连接。
答案 1 :(得分:8)
我知道这个问题比较老,但我觉得还有另一种方法未得到充分利用:
您可以将表连接回自己并使用运算符查找“最新”记录。
<强>答案强>
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(上面的第一条记录)没有找到“更新”的推荐(针对相同的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
此时,只需从SELECT中删除您的R_NEWER列,因为它们不再需要,您就可以得到答案。
重要的是要记住,在发生连接之后应用“where”,但ON语句在连接时发生。为了让我更容易理解,我总是尝试编写SELECT和JOIN并从我加入的每个表中返回列,然后在我清楚了解返回的内容后添加我的WHERE子句。
<强>买者强> 这种方法在大多数情况下效果很好,但是如果您有2个推荐(对于相同的CarePlanId)且日期为05/15/12并且该日期是“最新的”,则可能会有重复的行。要解决这个问题,如果出现这种情况,您可以根据“最高”的ReferralId将您的联接扩展到限制。
答案 2 :(得分:1)
只是一个猜测。我不确定EF是否会出现CTE语法问题 - 您是否可以强制EF调用存储过程,这样您就不会被EF支持的功能子集戴上手铐?
;WITH r AS
(
SELECT CarePlanId, MAX(ReferralDate)
FROM dbo.Referrals GROUP BY CarePlanId
)
SELECT * FROM dbo.CarePlan AS c
LEFT OUTER JOIN r
ON r.CarePlanId = c.CarePlanId;