【问题标题】:Updating some columns of one row from another of same table从同一表的另一行更新某一行的某些列
【发布时间】:2017-02-05 21:11:32
【问题描述】:

我有一些看起来像这样的数据:http://sqlfiddle.com/#!6/21a06/1

id   step   valA   valB   valC
------------------------------
100  1      NULL   2      3
101  2      4      5      6
102  3      7      NULL   9
103  3      10     11     12
104  4      13     14     15
105  4      NULL   14     15
106  5      NULL   18     19
107  5      20     18     19

id 是一个独特的字段。我正在尝试提出一个查询,该查询将从下一行的某些列(在此示例中为 valA 和 valB)中更新给定行上的值。仅当两行的 'step' 匹配时(永远不会期望超过两行匹配),如果第一行上 valA 或 valB 列的值为 NULL(具有较低的 listid 值),则相同的值下一行的列被复制到第一行。

因此,在上面给出的表格示例中,id=102 的行应该将 valB 更新为 11(以匹配 id=103 的下一行的 valB)。此外,id=106 的行应该将 valA 更新为 20(以匹配 id=107 的下一行的 valA)。任何给定的行对可能同时满足 valA 和 valB 的条件(均为 NULL)。 id=100 行不受影响,因为没有其他行具有 step=1,并且 id=105 行也不受影响,因为 NULL 位于“step”对的第二行。

结果如下所示:

id   step   valA   valB   valC
------------------------------
100  1      NULL   2      3
101  2      4      5      6
102  3      7      11     9
103  3      10     11     12
104  4      13     14     15
105  4      NULL   14     15
106  5      20     18     19
107  5      20     18     19

如果它更容易,id=105 行上的 NULL 也可以更新为 id=104 行 (13) 中的值,但这不是必需的。

我发现了一些看起来相关的问题,我尝试了各种内部连接等方法,但无法提出任何可行的方法。这超出了我的基本 SQL 经验。任何帮助表示赞赏。

【问题讨论】:

    标签: sql-server sql-server-2005


    【解决方案1】:

    您可以使用ROW_NUMBER 获取匹配对的第一行。然后使用APPLY 从第二对中获取替代值。

    WITH CTE AS(
        SELECT *,
            Rn = ROW_NUMBER() OVER(PARTITION BY step ORDER BY id)
        FROM TestTable
    )
    SELECT
        c.id, 
        c.step, 
        valA = ISNULL(c.valA, x.valA), 
        valB = ISNULL(c.valB, x.valB),
        c.valC
    FROM CTE c
    OUTER APPLY(
        SELECT TOP(1) *
        FROM TestTable t
        WHERE
            t.id > c.id
            AND t.step = c.step
        ORDER BY t.id
    ) x
    WHERE
        Rn = 1
        OR (c.valA IS NULL OR c.valB IS NULL)
    
    UNION ALL
    
    SELECT
        id, step, valA, valB, valC
    FROM CTE
    WHERE
        Rn = 2
        AND valA IS NOT NULL
        AND valB IS NOT NULL
    ORDER BY Id;
    

    ONLINE DEMO

    【讨论】:

    • 谢谢!我正在通过它来了解它如何更好地工作,但看起来它可以满足我的需要。似乎对 c 进行了更改,而不是对原始表进行了更改。例如。如果我从 TestTable 中选择 *,我会得到原始数据。是否可以这样做,以便修改原始表行?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-03-22
    • 2019-03-05
    • 1970-01-01
    • 1970-01-01
    • 2021-09-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多