代码:
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值并且保持VAL不从T2时跳过该T1.ID2的输出对于NOT-NULL T2.ID2s。表现必须快!!!!
期望的输出:
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];
答案 0 :(得分:2)
您的查找表中有一个默认值。您可以使用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
具有令人惊讶的良好性能特征。