代码:
CREATE TABLE [dbo].[T1] ( [ID1] INT NOT NULL, [ID2] INT NOT NULL );
CREATE TABLE [dbo].[T2] ( [ID1] INT NOT NULL, [ID2] INT NULL, [VAL] INT NOT NULL );
INSERT INTO [dbo].[T1] ( [ID1], [ID2] )
VALUES ( 1, 1 )
,( 1, 2 )
,( 1, 3 )
,( 1, 4 )
,( 1, 5 )
,( 2, 1 );
INSERT INTO [dbo].[T2] ( [ID1], [ID2], [VAL] )
VALUES ( 1, NULL, 25000 )
,( 1, 2, 30000 )
,( 2, NULL, 30000 );
目标:
T1 具有 ID1 和 ID2 映射的完整列表。
T2 是一个外部表,其中一些 ID1/ID2 映射到 Val。
最终目标是当 T2.ID2 = NULL 时“交叉连接”T1 和 T2 (ID1/ID2),但当 T2.ID2 具有 NOT NULL 值时跳过 T1.ID2 的输出并保留 T2 中的 VAL对于 NOT-NULL T2.ID2。性能必须快!!!
期望的输出:
ID1 ID2 VAL
1 1 25000
1 2 30000 -- T1.ID2 = 2 takes the priority
1 3 25000
1 4 25000
1 5 25000
2 1 30000
我的尝试:
SELECT [T2].[ID1]
, [T1].[ID2]
, [T2].[VAL]
FROM [dbo].[T1] [T1]
JOIN [dbo].[T2] [T2]
ON [T1].[ID1] = [T2].[ID1]
WHERE [T2].[ID2] IS NULL
OR [T1].[ID2] IN (SELECT [T3].[ID2]
FROM [dbo].[T2] [T3]
WHERE [T2].[ID1] = [T3].[ID1]
AND [T2].[ID2] = [T3].[ID2] )
--ORDER BY [T2].[ID1]
-- , [T1].[ID2]
-- , [T2].[VAL];
当前输出:
ID1 ID2 VAL
1 1 25000
1 2 25000
1 3 25000
1 4 25000
1 5 25000
1 2 30000
2 1 30000
DROP TABLE [dbo].[T1];
DROP TABLE [dbo].[T2];
最佳答案
您的查找表中有一个默认值。您可以使用 left join
和 coalesce()
来解决此问题:
select t1.id1, t1.id2,
coalesce(t2.val, t2default.val) as val
from t1 left join
t2
on t1.id1 = t2.id1 and t1.id2 = t2.id2 left join
t2 t2default
on t1.id1 = t2default.id1 and t2default.id2 is null;
假设您在连接中使用的 id 列上有正确的索引,那么性能应该非常好。
如果您关心性能,另一种方法可能值得尝试:
select t1.id1, t1.id2, t2.val
from t1 outer apply
(select top 1 t2.*
from t2
where t2.id1 = t1.id and (t2.id2 is null or t2.id2 = t1.id2)
order by (case when t2.id2 = t1.id2 then 1 else 2 end)
) t2;
这对我来说似乎更复杂,但有时 apply
具有令人惊讶的良好性能特征。
关于sql - T-SQL 连接 NULL 和 NOT NULL 记录,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40899317/