2013-12-10 132 views
0

這是一個基本的左連接問題,我讀了很多文章解釋發生了什麼,但不知何故解決方案沒有點擊我的腦海。我的左表有獨特的記錄。我的右表有幾個記錄在左邊的每個記錄。左加入結果額外記錄

在我一直在閱讀的文章中,常常解釋爲左表有客戶,右表有訂單。這是非常相似,但不完全是我所面臨的。

在我的情況左表有唯一的記錄,右邊有重複的數據要遷移到數據庫左表所以我試圖編寫一個查詢,將加入共享的密鑰,但我只需要從右側記錄一條記錄。我得到的結果當然有多條記錄,因爲單個左邊的匹配在右邊多次。

我想我需要添加某種過濾,如Top(1),但仍閱讀/學習,並想從這個名單上的brainiacs反饋/方向。

以下是我與工作的一個簡單的模式:

DECLARE @Customer TABLE 
(
Id int, 
Name varchar(50), 
email varchar(50) 
) 

INSERT @Customer VALUES(1, 'Frodo', '[email protected]') 
INSERT @Customer VALUES(2, 'Bilbo', '[email protected]') 
INSERT @Customer VALUES(3, 'Galadriel', '[email protected]') 
INSERT @Customer VALUES(4, 'Arwen', '[email protected]') 
INSERT @Customer VALUES(5, 'Gandalf', '[email protected]') 

DECLARE @CustomerJobs TABLE 
(
Id int, 
email varchar(50), 
jobname varchar(50) 
) 

INSERT @CustomerJobs VALUES(1, '[email protected]', 'RingBearer') 
INSERT @CustomerJobs VALUES(2, '[email protected]', 'RingBearer') 
INSERT @CustomerJobs VALUES(3, '[email protected]', 'RingBearer') 
INSERT @CustomerJobs VALUES(4, '[email protected]', 'RingBearer') 
INSERT @CustomerJobs VALUES(5, '[email protected]', 'RingBearer') 
INSERT @CustomerJobs VALUES(6, '[email protected]', 'Burglar') 
INSERT @CustomerJobs VALUES(7, '[email protected]', 'Burglar') 
INSERT @CustomerJobs VALUES(8, '[email protected]', 'Burglar') 
INSERT @CustomerJobs VALUES(9, '[email protected]', 'MindReader') 
INSERT @CustomerJobs VALUES(10, '[email protected]', 'Evenstar') 
INSERT @CustomerJobs VALUES(10, '[email protected]', 'Evenstar') 
INSERT @CustomerJobs VALUES(11, '[email protected]', 'WhiteWizard') 
INSERT @CustomerJobs VALUES(12, '[email protected]', 'WhiteWizard') 


SELECT 
Cust.Name, 
Cust.email, 
CJobs.jobname 

FROM 
@Customer Cust 

LEFT JOIN @CustomerJobs CJobs ON 
Cjobs.email = Cust.email 

我與ROW_NUMBER玩弄過的分區()作爲也許我應該與ROW_NUMBER在分區加入到熱膨脹係數,而不是桌子本身?

我有另一個約束是我無法從右表中刪除重複項。

所以再次我爲簡單的問題表示歉意,並感謝您的幫助。

+0

從右邊只需要一條記錄是什麼意思?哪個記錄?或者你是否只關心正確的桌子有任何記錄但不關心哪個記錄?在你的例子中,他們總是同一個人的記錄;你的所有數據都是這種情況嗎? – mayabelle

+0

我只需要添加到我的左數據庫的工作名稱,因爲這是重複的權利,我不關心它使用哪個記錄我只是想要它一次。 – GPGVM

回答

1

如果不使用LEFT JOIN,使用外部應用的...然後你可以使用top子句限制返回的行...

select 
    Cust.Name 
, Cust.email 
, CJobs.jobname 
from @Customer Cust 
outer apply (
    select top 1 * 
    from @CustomerJobs CJobs 
    where Cjobs.email = Cust.email 
) cjobs; 
+0

我在實踐中發現,這往往比row_numbers或區別更快,但當然嘗試所有選項以確保它依賴於它提出的查詢計劃。 –

+0

我發現每個人的答案都非常有幫助,但是這個教會了我一些新的東西,那就是APPLY運算符。從技術網:有兩種形式的申請:交叉申請和外部申請。CROSS APPLY僅從外部表中返回生成表值函數結果集的行。 OUTER APPLY返回產生結果集的行和不包含表值函數生成的列中的NULL值的行。 – GPGVM

+0

基本上,交叉應用是內連接,因爲外應用是左連接。 –

1

你必須想出一些人爲的方法,將第二個表格減少爲每個電子郵件一行。例如:

SELECT 
Cust.Name, 
Cust.ID, 
Cust.email, 
CJobs.jobname 

FROM 
@Customer Cust 

LEFT JOIN 
(select min(id) as id,email, jobname 
from 
@CustomerJobs 
group by email, jobname) as CJobs ON 
Cjobs.email = Cust.email 

但這是非常隨機的。有沒有辦法確定你的CustomerJobs表中的哪一行是「正確」的?

+0

AFAIK /可以告訴細讀他們是真正相同的數據,所以他們都是正確的,因此我只需要一個....任何一個。 – GPGVM

1
SELECT DISTINCT 
Cust.Name, 
Cust.email, 
CJobs.jobname 

FROM 
@Customer Cust 

LEFT JOIN @CustomerJobs CJobs ON 
Cjobs.email = Cust.email 

DISTINCT關鍵字的額外內容應該可以讓你得到你想要的。

1

這將工作:

SELECT 
    Cust.Name, 
    Cust.ID, 
    Cust.email, 
    CJobs.jobname 
FROM @Customer Cust 
LEFT JOIN 
    (SELECT DISTINCT email, jobname 
    FROM @CustomerJobs) C2 ON C2.email = C.email 
+0

FYI截然不同,並在這裏是多餘的... –

+0

對不起,匆忙。是的,分組是不需要的。然而,我認爲需要截然不同,因爲在該表中有多個具有相同電子郵件和作業名稱的行。 – mayabelle

+0

是的,你需要一個或另一個 - 即使在查詢計劃中,所有列和使用不同的分組也是等價的。 –