【问题标题】:TSQL - Fill missing recordsTSQL - 填充缺失的记录
【发布时间】:2018-09-14 14:48:58
【问题描述】:

代码:

CREATE TABLE #Temp
    (
        [ID1] INT
      , [ID2] INT
      , [ID3] INT
      , [Val] BIT
      , PRIMARY KEY CLUSTERED ( [ID1], [ID2], [ID3] )
    ) ;
INSERT INTO #Temp
SELECT  1
      , 10
      , 100
      , 1
UNION ALL
SELECT  1
      , 10
      , 101
      , 1
UNION ALL
SELECT  1
      , 11
      , 100
      , 1
UNION ALL
SELECT  1
      , 11
      , 101
      , 1
UNION ALL
SELECT  2
      , 10
      , 100
      , 1 ;

CREATE TABLE #Temp_ID3
    (
        [ID3] INT
    ) ;
INSERT INTO #Temp_ID3
SELECT  100
UNION ALL
SELECT  101
UNION ALL
SELECT  102 ;

SELECT  [ID1]
      , [ID2]
      , [ID3]
      , [Val]
FROM    #Temp ;

SELECT  [ID3]
FROM    #Temp_ID3 ;

DROP TABLE #Temp_ID3 ;
DROP TABLE #Temp ;

输出:

ID1 ID2 ID3 Val
1   10  100 1
1   10  101 1
1   11  100 1
1   11  101 1
2   10  100 1

目标: 从 #Temp_ID3 表中查找缺失的 ID3 记录 - 在 #Temp 表中(现有 ID1/ID2 组合的 ID1/ID2/ID3 组合)。对于那些缺失的记录,Val 应该是 False。期望的输出是有意义的。

我可以从#Temp 中获得不同的 ID1/ID2,与 ID3 交叉连接并创建数据集。将 #Temp 左连接到这个新数据集,并以这种方式插入记录,但正在寻找一种更“更简单”的方式。

这是“复杂”的方式。

;WITH CTE AS
    (
        SELECT      DISTINCT
                    [TT].[ID1]
                  , [TT].[ID2]
                  , [T3].[ID3]
        FROM        #Temp_ID3 AS [T3]
        CROSS JOIN  (
                        SELECT  DISTINCT
                                [ID1]
                              , [ID2]
                        FROM    #Temp
                    ) AS [TT]
    )
SELECT      [C].[ID1]
          , [C].[ID2]
          , [C].[ID3]
          , COALESCE ( [TT].[Val], 0 ) AS [Val]
FROM        CTE     AS [C]
LEFT JOIN   #Temp   AS [TT]
ON          [C].[ID1]     = [TT].[ID1]
            AND [C].[ID2] = [TT].[ID2]
            AND [C].[ID3] = [TT].[ID3]
ORDER BY    [C].[ID1]
          , [C].[ID2]
          , [C].[ID3] ;

期望的输出:

ID1 ID2 ID3 Val
1   10  100 1
1   10  101 1
1   10  102 0       -- Filling Missing ID3 Record w/ default Val = 0
1   11  100 1
1   11  101 1
1   11  102 0       -- Filling Missing ID3 Record w/ default Val = 0
2   10  100 1
2   10  101 0       -- Filling Missing ID3 Record w/ default Val = 0
2   10  102 0       -- Filling Missing ID3 Record w/ default Val = 0

【问题讨论】:

  • 不,就是这样。
  • 哦不...... :(

标签: sql sql-server tsql sql-server-2012


【解决方案1】:

例如,您只需要 cross joinself join

select distinct t.id1, t.id2, t3.id3, coalesce(t1.val, 0) as Val 
from #Temp t cross join #Temp_ID3 t3
left join #temp t1 
          on t1.id1 = t.id1 and t1.id2 = t.id2 and t1.id3 = t3.id3;

【讨论】:

    【解决方案2】:

    使用cross join 生成行,然后使用left join 填写值:

    select t1.id1, t2.id2, t3.id3, coalesce(t.val, 0) as val
    from (select distinct id1 from #temp) t1 cross join
         (select distinct id2 from #temp) t2 cross join
         (select distinct id3 from #temp) t3 left join
         #temp t
         on t.id1 = t1.id1 and t.id2 = t2.id2 and t.id3 = t3.id3;
    

    如果其中一张表确实有 ID,则不必使用子查询来生成 ID。

    编辑:

    对于评论中的修改版,可以做非常类似的事情:

    select t12.id1, t12.id2, t3.id3, coalesce(t.val, 0) as val
    from (select distinct id1, id2 from #temp) t12 cross join
         #temp_id3 t3 left join
         #temp t
         on t.id1 = t12.id1 and t.id2 = t12.id2 and t.id3 = t3.id3;
    

    【讨论】:

    • 感谢 Gordon 的快速建议。我应该在OP中更清楚一点。我们只需要为现有的 ID1/ID2 组合查找缺失的 ID3 记录。例如,(根据您查询的输出),我们不需要为 ID1 = 2 和 ID2 = 11 填充任何缺失记录。我们只需要为 ID1 = 2 和 ID2 = 1-0 填充缺失记录因为这就是全部存在(在这种情况下,我们缺少 ID3 = 101 和 102)。
    猜你喜欢
    • 1970-01-01
    • 2023-02-22
    • 1970-01-01
    • 2019-09-23
    • 1970-01-01
    • 2012-10-25
    • 1970-01-01
    相关资源
    最近更新 更多