我有一个(我认为)复杂的问题,并且不知道如何在SQL(全天)中这样做。我已经把逻辑转了几次,总是缺少一些东西。
两个表之间存在一个连接,它对第三个表有不同的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(不能UNION-&gt; DISTINCT - 这也会选择NULL)< / p>
答案 0 :(得分: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
中的列顺序而变化
ISNULL(t2.FK_Id_2, t1.FK_Id_1)
与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