sql - T-SQL 连接 NULL 和 NOT NULL 记录

标签 sql sql-server sql-server-2016

代码:

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 joincoalesce() 来解决此问题:

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/

相关文章:

php - SQL select 语句中的语法错误

c# - 如何在datagridview c#中只显示我的查询结果

SQL Server - 使用交叉应用或 openjson 或任何东西递归地进入嵌套的 JSON 数组

SQL Server 2016 - 动态数据屏蔽 (DDM)

sql - 对于具有大量数据的表,将数据类型从 varchar 更改为 nvarchar

MySQL 日期问题 - 如何计算?

sql - 如何使用ssisdb在运行过程中获取ssis包执行信息

sql - T-SQL : Why is my query faster, 如果我使用表变量?

c# - SQL 超时和查询性能

执行 20 万行 SQL 查询需要一个多小时