在SQL Server 2012中基于row_number更新行

时间:2014-11-25 08:56:56

标签: sql sql-server sql-server-2012 cursor sql-update

我已经在电子表格中获得了一些数据,这些数据很快将进入自动导入,因此我无法在电子表格上进行任何手动输入。数据基本上包含以下列。 Trayid,trayname,itemdescription和rownumber。我自己没有构建这些表,或者我会以不同的方式构建它,但我必须坚持已经设置的格式。

将导入正在导入的数据。

Trayid | Trayname | ItemDescription | RowNumber
1        Tray 1     Product 1         1
                    Product 2         2
                    Product 3         3
                    Product 4         4
2        Tray 2     Product 1         1
                    Product 2         2
                    Product 3         3
                    Product 4         4
                    Product 5         5

我需要做的是更新第1行之后的其他每一行的trayid和trayname,例如它看起来像。

Trayid | Trayname | ItemDescription | RowNumber
1        Tray 1     Product 1         1
1        Tray 1     Product 2         2
1        Tray 1     Product 3         3
1        Tray 1     Product 4         4
2        Tray 2     Product 1         1
2        Tray 2     Product 2         2
2        Tray 2     Product 3         3
2        Tray 2     Product 4         4
2        Tray 2     Product 5         5

我猜我需要使用光标或其他东西,但我不确定,我认为可以通过沿着rownumbers下来并在它再次看到rownumber 1然后继续使用下一个trayid时停止trayname。

很抱歉,如果我需要的东西没有意义,那就很难解释。

1 个答案:

答案 0 :(得分:1)

SQL表没有固有的顺序。所以你不能依赖它。但是,你可以做些什么:

  • 在源表中定义identity列。
  • 在源表上创建一个排除标识的视图。
  • 批量插入视图。

这将按照与原始数据相同的顺序为行分配序号。我们称之为id。然后,您可以执行以下操作进行更新:

with toupdate (
      select t.*,
             max(TrayId) over (partition by grp) as new_TrayId,
             max(TrayName) over (partition by grp) as new_TrayName
      from (select t.*,
                   count(TrayId) over (order by id) as grp
            from t
           ) t
     )
update toupdate
    set TrayId = new_TrayId,
        TrayName = new_TrayName
    where TrayId is null;

这个想法是定义与每个托盘相对应的行组。简单的想法是在任何给定行之前计算非NULL值的数量 - 组中的所有内容将具有相同的grp值。然后,窗口函数将实际值扩展到组中的所有行(使用max()),这些值用于更新。