2012-03-06 59 views
13

我基本上需要做兩個表(CarePlan和推薦)的左外連接問題是我需要最新的推薦如果它存在,它的好如果沒有。SQL Server:左頂部加入頂部1以選擇最多一行

我有這2個查詢 1.加入CarePlan /推薦表 - 創建重複careplans如果有一個careplan多個引用,或具有完全沒有轉診信息(左外連接) 2.選擇頂部1根據日推薦,給予CarePlanId

我想這兩個,所以我抓住所有的careplans和轉診如果它存在,如果它不合並 - 只需要最新的轉診

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 

最後,我希望有一個查詢,讓我與擁有最新的日期,或者爲null,推薦,如果它不必須請示careplans它

這樣的:

CarePlanId ReferralId ReferralDate 
---------- ---------- ------------ 
1   1    05/15/12 
2   NULL   NULL 

謝謝 - 我希望這是有道理

+0

有困難readin什麼喲想,但我認爲你需要的是查找如何做cte或派生表。 – HLGEM 2012-03-06 22:25:06

+0

你能展示樣本數據和期望的結果嗎?像@HLGEM一樣,你不清楚你開始的地方以及你想要結束的地方。 – 2012-03-06 22:30:47

+0

您需要交叉申請。 – usr 2012-03-06 22:33:16

回答

38
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

只是一個猜測。我不確定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; 
+0

對不起 - 我猜它更像是一個通用的SQL問題,實體框架在這裏不重要 - 至少我希望。我也希望返回的護理計劃是不同的(只有一個使用最新的推薦) – Jerrold 2012-03-06 22:36:44

+0

只有您可以告訴我們後者 - 您是否已經調整好運行查詢?它是否會返回您期望的結果?如果您向我們展示樣本數據和您期望的輸出結果,那麼我們在將它們投擲到牆上之前嘗試我們的答案要容易得多。這也節省了每個人的時間。 – 2012-03-06 22:44:51

6

我知道這個問題是舊的,但有另一種方法,我覺得是下-utilized:

您可以將表格加回自己並使用操作員查找「最近」記錄。

回答

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相關的每個其他推薦記錄中,但只有在有較新的推薦日期。

這裏是沒有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列他們不再需要,你有你的答案。

重要的是要記住,「where」適用於連接發生後,但ON語句發生在連接時。爲了讓我更容易理解,我總是嘗試寫入SELECT和JOIN,並從每個我加入的表中返回列,然後添加我的WHERE子句,一旦我清楚瞭解返回的內容。

買者 這種方法適用於大多數情況下,偉大的,但它是可能的,如果你有2個推薦(同一CarePlanId)與05/15/12日期有重複的行和日期是「最近的。「要解決這個問題,如果出現這種情況,可以根據「最高」引用Id擴展聯接。