0

我有一个(我认为)复杂的问题,并且不知道如何在 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->DISTINCT - 这也会选择 NULL)

4

1 回答 1

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
于 2013-07-23T13:45:28.427 回答