2013-07-22 44 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个这样的列对吗? –