【问题标题】:How to update the first row with its second row values in case some columns are duplicates如果某些列重复,如何使用第二行值更新第一行
【发布时间】:2020-02-21 17:22:45
【问题描述】:

所以让我们假设我有一个表 products 我有以下数据

+-----------+-------------+-------+
| ProductID | ProductName | Value |
+-----------+-------------+-------+
|         1 | Box         | NULL  |
|         2 | PEN         | 10    |
|         3 | BOX         | 10    |
|         4 | KITE        | 20    |
+-----------+-------------+-------+

现在我想像下面这样更新表格

+-----------+-------------+-------+
| ProductID | ProductName | Value |
+-----------+-------------+-------+
|         1 | Box         | 10    |
|         2 | PEN         | 10    |
|         3 | BOX         | 10    |
|         4 | KITE        | 20    |
+-----------+-------------+-------+

如您所见,我需要找到所有具有 null 的产品名称,并使用具有相同名称的产品中的值更新它们。

假设我们可能有多个带有 null 的“盒子”,并且所有“盒子”都将具有相同的值和大量数据。

【问题讨论】:

  • 如果相同的product 有不同的value 怎么办?你想更新哪一个?

标签: sql sql-server


【解决方案1】:

对于包含相同产品的许多行,自联接可能无法很好地扩展。这是一种避免自连接的简单方法。这仅在存在与实际数据匹配的列时更新包含 null 的列。

;WITH CTE as
(
  SELECT
    [Value],
    max([Value])over(partition by Productname)NewValue
  FROM [YourTable]
)
UPDATE CTE 
SET [Value] = NewValue
WHERE [Value] is null and NewValue is not null

【讨论】:

    【解决方案2】:

    我们可以在这里尝试使用自联接:

    WITH cte AS (
        SELECT p2.Value AS ValueSource, p1.Value AS ValueTarget
        FROM products p1
        INNER JOIN products p2
            ON p1.ProductName = p2.ProductName AND
               p2.Value IS NOT NULL AND p1.Value IS NULL
    )
    
    UPDATE cte
    SET ValueTarget = ValueSource;
    

    这里的想法是将具有相同产品名称但产品 ID 值不同的记录配对。然后,我们用非NULL 值更新具有NULL 值的“重复”。

    【讨论】:

    • @t-clausen.dk 最初并不清楚NULL 是这里的标准。
    【解决方案3】:

    你可以使用子查询:

    update p 
        set p.value = (select max(p1.value) 
                       from Product p1 
                       where p1.productname = p.productname and p1.value is not null
                      )
    from Product p
    where p.value is null;
    

    【讨论】:

      【解决方案4】:

      首先找到所有具有相同产品名称的记录。 然后应用行号并将其保存在 CTE 稍后将此表与主表连接,并使用 case 条件检查 null 并更新它。 where claue 将减少从 CTE 返回的记录数(因为我们不需要 null 值)

      ;WITH cte AS
      (
        SELECT
            ROW_NUMBER() OVER(PARTITION BY ProductName  ORDER BY ProductName ) AS rno,
            ProductID,Value,ProductName 
        from Product where ProductName in
      (SELECT ProductName FROM Product Group By(ProductName) having count(ProductName)>1)
      )
      
      
      Update FR SET FR.Value = CASE WHEN FR.Value IS NULL THEN CTE.Value ELSE FR.Value END
      from Product FR
      inner join CTE CTE on CTE.ProductName = FR.ProductName
      where CTE.Value is not null
      

      【讨论】:

        【解决方案5】:

        Demo on db<>fiddle

        你可以使用ROW_NUMBER()结合CTE来实现。

        ;with cte as (
         select ProductName, ROW_NUMBER() OVER (PARTITION BY ProductName ORDER BY [Value]) rn,Value 
         from #a
        )
        update #a
        set #a.Value = cte.Value
        from #a
        inner join cte on cte.ProductName = #a.ProductName
        where rn <> 1--#a.Value is null and cte.Value is not null
        

        【讨论】:

        • @Tejaswi Pandava 这能回答你的问题吗?如果您需要任何帮助,请告诉我
        猜你喜欢
        • 2020-10-23
        • 2021-08-18
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-11-09
        • 2022-11-03
        • 2013-03-03
        • 1970-01-01
        相关资源
        最近更新 更多