【问题标题】:Update table from self table where value in the column is not null从列中的值不为空的 self 表更新表
【发布时间】:2019-01-15 06:49:28
【问题描述】:

我有一个包含值的表:

dbid    name         userid
------------------------------
154     xyz          NULL
987     xyz          NULL
777     xyz          5
111     abc          NULL
745     abc          NULL
748     abc          6

预期输出:

dbid     name     userid
------------------------------
154     xyz          5
987     xyz          5
777     xyz          5
111     abc          6
745     abc          6
748     abc          6

除了一对一名称之外,userid 列中的所有值均为空值。我想为 name = 'xyz' 的所有行在用户 ID 中设置 5。 同样,要更新表以在 userid where name = 'abc' 中设置 6。

对于上述场景,更新表的查询应该是什么?

注意:以上只是一个例子。我有一个包含数十万条记录的表。我不能在查询中写 id 5 或 6。

【问题讨论】:

  • 请不要在此处使用非英语单词,例如“lakh”。这会让人们感到困惑。
  • 如果您的问题已解决 - 将答案标记为已接受

标签: sql sql-server tsql sql-update


【解决方案1】:

试试这个

update table_name 
   set table_name.userid = (
        select top(1) ss.userid 
          from table_name ss 
         where ss.name = table_name.name 
           and ss.userid is not null
        ) 
    where table_name.userid is null

此查询正在搜索名称相同的第一条记录 userid,如果 userid 为空,则更新

【讨论】:

  • 如你所说,有很多行。如果它工作缓慢,只需按名称添加索引,
【解决方案2】:

鉴于name 表示userid,您可以使用单个UPDATE 语句更新您的表。您可以使用以下查询,但前提是仅存在这些对属性的唯一依赖关系。

UPDATE table_name
SET name = (SELECT TOP 1 temp.userid FROM table_name temp WHERE temp.name = name)
WHERE userid is null;

【讨论】:

  • 你也应该考虑@Victor Ermakov的回答,因为子查询也应该包含temp.userid is not null
【解决方案3】:

我应该假设表定义中的列 dbid 和 name 不为空吗?那么问题也是“输出”,您希望它作为查询、视图还是 SP 的结果?无论如何,简单地说,我会亲自将桌子分成两张桌子。

表 1:

dbid     name  
---------------
154     xyz    
987     xyz    
777     xyz    
111     abc    
745     abc    
748     abc

表 2:

name     userid
------------------
xyz      5
abc      6

然后,当我想要特定 dbid 的用户 ID id 时,我会简单地:

SELECT A.dbid, A.name, B.userid FROM DATABASE.TABLE1 A INNER JOIN DATABASSE.TABLE2 B ON A.name = B.name

这将导致输出表:

dbid     name     userid
------------------------------
154     xyz          5
987     xyz          5
777     xyz          5
111     abc          6
745     abc          6
748     abc          6

【讨论】:

    【解决方案4】:

    试试这个:

    DECLARE @DataSource TABLE
    (
        [dbid] INT
       ,[name] SYSNAME
       ,[userid] SMALLINT
    );
    
    INSERT INTO @DataSource ([dbid], [name], [userid])
    VALUES (154, 'xyz', NULL)
          ,(987, 'xyz', NULL)
          ,(777, 'xyz', 5)
          ,(111, 'abc', NULL)
          ,(745, 'abc', NULL)
          ,(748, 'abc', 6);
    
    WITH DataSource AS
    (
        SELECT [dbid]
              ,[name]
              ,[userid]
              ,MIN([userID]) OVER (PARTITION BY [name]) AS [userid_precalc]
        FROM @DataSource
    )
    UPDATE DataSource
    SET [userid] = [userid_precalc]
    WHERE [userid] IS NULL;
    
    SELECT *
    FROM @DataSource;
    

    【讨论】:

      【解决方案5】:

      请尝试以下查询

      update table_name
      set userid=(select top 1 T.userid from table_name T where T.name=table_name.name and T.userid is not null )
      where userid is null
      

      【讨论】:

        【解决方案6】:

        试试这个:

        1) 将您的数据选择到一个虚拟表中。

        SELECT * INTO dummy_tbl FROM myTable WHERE userid is not null
        

        查询应插入所有用户ID不为空的数据。

        2) 执行更新命令

        update myTable set userid = (select userID from dummy_tbl where dummy_tbl.name  = myTable.name)
        

        3) 删除您创建的虚拟表。

        drop table dummy_tbl
        

        一切顺利,所有用户 ID 已相应更新。

        BR,莫伊德

        【讨论】:

          【解决方案7】:

          使用两个更新查询

          update table_name
          set userid=5
          where name = 'xyz';
          update table_name
          set userid=6
          where name = 'abc';
          

          【讨论】:

          • 这只是问题中的一个例子。我有一个包含十万条记录的表......我不能在查询中写 id 5 或 6。我需要一个更新十万条记录的查询。
          【解决方案8】:

          由于您有十万条记录要更新表变量,因此应避免使用窗口函数。

          我的想法类似于@Moiyd。

          首先在原始表名列上创建非聚集索引。如果用户还没有聚集索引,那么,

          Create Non Clustered index ix_myTable_name on myTable(name) include(userid)
          

          如果 userid 是 CI 则不需要

          include(userid)
          

          将非空名称和用户 ID 存储在单独的表中。

          Create table dummy_tbl (name varchar(100),userid int)
          
          Create Non Clustered index ix_dummy_name on dummy_tbl(name) include(userid)
          
          insert into dummy_tbl (userid,name)
          SELECT userid  FROM myTable WHERE userid is not null
          
          update T 
          set userid = T.userid
          from myTable T
          inner join dummy_tbl d on d.name  = T.name
          
          Drop table dummy_tbl .
          

          如果可能永久存储 dummy_tbl 的值,因为这是最好的,normalise 方式。您可以将所有 non repeating 列存储在 dummy_tbl

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2022-11-02
            • 1970-01-01
            • 1970-01-01
            • 2013-03-08
            • 2017-05-30
            • 1970-01-01
            • 2021-07-11
            相关资源
            最近更新 更多