2013-07-22 47 views
0

我有一個(我認爲)複雜的問題,並不知道如何在SQL(整個一天)中做到這一點。我已經把這個邏輯轉了幾次,總是缺少一些東西。JOIN 2表格從2列中獲得唯一值

兩個表之間有一個連接,它們將不同的FK引用保存到第三個表中。

如何加入這兩張表,所以我確定所有的FK組合都已經出現,並且都是獨一無二的? 我需要將2個FK列合併爲一個,所以我可以稍後加入到第3個。空值是可能的。由不可能的集團,因爲我需要知道的記錄是從(需要ID_1和ID_2的結果)

這裏的示例代碼:

DECLARE @T1 TABLE (Id int, CommonId int, FK_Id_1 int) 
DECLARE @T2 TABLE (Id int,CommonId int, FK_Id_2 int) 


INSERT INTO @T1 VALUES (1,1,1) 
INSERT INTO @T1 VALUES (2,1,2) 
INSERT INTO @T1 VALUES (3,2,3) 
INSERT INTO @T1 VALUES (4,3,NULL) 
INSERT INTO @T1 VALUES (5,4,NULL) 

INSERT INTO @T2 VALUES (11,1,1) 
INSERT INTO @T2 VALUES (12,2,2) 
INSERT INTO @T2 VALUES (13,2,3) 
INSERT INTO @T2 VALUES (14,4,5) 

SELECT t1.Id as Id_1,t2.Id as Id_2, t1.CommonId, t1.FK_Id_1, t2.FK_Id_2, 
COUNT(t1.FK_Id_1) OVER (PARTITION BY t1.FK_Id_1) AS T1_RANK, 
COUNT(t2.FK_Id_2) OVER (PARTITION BY t2.FK_Id_2)AS T2_RANK 
FROM @T1 t1 
FULL JOIN @T2 t2 on t1.CommonId = t2.CommonId 
ORDER BY CommonId 

該查詢返回的:

Id_1  Id_2  CommonId FK_Id_1  FK_Id_2  T1_RANK  T2_RANK 
----------- ----------- ----------- ----------- ----------- ----------- ----------- 
1   11   1   1   1   1   2 
2   11   1   2   1   1   2 
3   12   2   3   2   2   1 
3   13   2   3   3   2   1 
4   NULL  3   NULL  NULL  0   0 
5   14   4   NULL  5   0   1 

,我需要以某種方式,使它看起來像這樣:

Id_1  Id_2  CommonId FK_Id 
----------- ----------- ----------- ----------- 
1   11   1   1 
2   11   1   2 
3   12   2   2 
3   13   2   3 
4   NULL  3   NULL 
5   14   4   5 

我不喜歡的東西SELECT COALESCE(FK_Id_1,FK_Id_2) AS FK_Id但這總是優先選擇T1。我正在考慮根據重複值切換優先級的方式。

我有一個醜陋的解決方案,看起來像這樣,但我正在尋找更好的想法。

;WITH tmp as (
SELECT t1.Id as Id_1,t2.Id as Id_2, t1.CommonId, t1.FK_Id_1, t2.FK_Id_2, 
COUNT(t1.FK_Id_1) OVER (PARTITION BY t1.FK_Id_1) AS T1_RANK, 
COUNT(t2.FK_Id_2) OVER (PARTITION BY t2.FK_Id_2)AS T2_RANK 
FROM @T1 t1 
FULL JOIN @T2 t2 on t1.CommonId = t2.CommonId) 
SELECT Id_1, Id_2, CommonId, 
CASE 
    WHEN T1_RANK > T2_RANK THEN COALESCE(FK_Id_2,FK_Id_1) 
    WHEN T2_RANK > T1_RANK THEN COALESCE(FK_Id_1,FK_Id_2) 
END AS FK_Id 
FROM tmp 
ORDER BY CommonId 

我不知道如果我正確地解釋了整個局面,我必須加入的表,因爲我有其他列只能從T1和T2(即將無法聯盟 - > DISTINCT - 這也是選擇NULL)

回答

0

只需選擇CommonId,然後完全加入到這兩個表中。

下面的查詢與您想要的結果匹配100%。

;WITH cte AS (
    SELECT CommonId FROM @T1 
    UNION SELECT CommonId FROM @T2 
) 
SELECT t1.Id AS Id_1, t2.Id AS Id_2, cte.CommonId, ISNULL(t2.FK_Id_2, t1.FK_Id_1) AS FK_Id 
FROM cte 
FULL OUTER JOIN @T1 t1 ON cte.CommonId = t1.CommonId 
FULL OUTER JOIN @T2 t2 ON cte.CommonId = t2.CommonId 

要注意的是,該FK_Id的結果與謂語

ISNULL(t2.FK_Id_2, t1.FK_Id_1)ISNULL列順序變化是不一樣的ISNULL(t1.FK_Id_1, t2.FK_Id_2)

在我看來這替代版本更符合您的要求,因爲它採用FK的兩個選項。

;WITH cte AS (
    SELECT CommonId FROM @T1 
    UNION SELECT CommonId FROM @T2 
) 
SELECT t1.Id AS Id_1, t2.Id AS Id_2, cte.CommonId, ISNULL(t2.FK_Id_2, t1.FK_Id_1) AS FK_Id--, cte.CommonId, * 
FROM cte 
FULL OUTER JOIN @T1 t1 ON cte.CommonId = t1.CommonId 
FULL OUTER JOIN @T2 t2 ON cte.CommonId = t2.CommonId 
UNION 
SELECT t1.Id AS Id_1, t2.Id AS Id_2, cte.CommonId, ISNULL(t1.FK_Id_1, t2.FK_Id_2) AS FK_Id--, cte.CommonId, * 
FROM cte 
FULL OUTER JOIN @T1 t1 ON cte.CommonId = t1.CommonId 
FULL OUTER JOIN @T2 t2 ON cte.CommonId = t2.CommonId 
+0

感謝您的回答。 第一個查詢在100%的情況下不起作用。 T1和T2應該沒有區別。樣本數據只是給出了T1的所有可能的組合,但不應該有T2在T1上的優先級。第二個腳本給出了所有可能性,但是我只需要唯一的可能性,因爲這個表有3-4個這樣的列對,並且所有組合對於1個組將是2(n),具有很多空值。 –

+0

@ d.popov,讓我們專注於第二個腳本。請你澄清:** 1)**你是什麼意思的「獨特的」?由於我在CTE和外部使用'UNION',所以重複被消除。 ** 2)**你可以請分享更多的細節,因爲這張桌子有3-4個這樣的列對嗎? –