有效更新980K条记录,其中行在组中具有最大值

时间:2019-02-12 09:29:13

标签: sql-server performance tsql sql-server-2016

我正在努力在合理的时间内更新数据库中的980,000条记录。

我必须在PriceID等于一个组的最大值(按ProductID分组)的行中将NextLp的值设置为'NULL'。

为直观起见,这是我的示例:

+-----------+---------+--------+---------------------+
| ProductID | PriceID | NextLp | Set NextLp to NULL? |
+-----------+---------+--------+---------------------+
| APPLE     | 1       | -      |                     |
+-----------+---------+--------+---------------------+
| APPLE     | 2       | -      |                     |
+-----------+---------+--------+---------------------+
| APPLE     | 3       | -      | Yes                 |
+-----------+---------+--------+---------------------+
| PEAR      | 1       | -      |                     |
+-----------+---------+--------+---------------------+
| PEAR      | 2       | -      | Yes                 |
+-----------+---------+--------+---------------------+

我尝试了各种方法,但是所有这些方法至少要花15秒来更新100条记录..还有979,100条要走-所以我的方法肯定不可行。

感谢您的帮助。

版本为MS SQL 2016

1 个答案:

答案 0 :(得分:4)

也许是这样吗?

DECLARE @tbl TABLE(ProductID VARCHAR(100),PriceID INT,NextLp VARCHAR(100));
INSERT INTO @tbl VALUES
 ('APPLE',1,'-')
,('APPLE',2,'-')
,('APPLE',3,'-')
,('PEAR ',1,'-')
,('PEAR ',2,'-');

WITH UpdatableCTE AS
(
    SELECT * 
          ,ROW_NUMBER() OVER(PARTITION BY ProductID ORDER BY PriceID DESC) AS Nr
    FROM @tbl 
)
UPDATE UpdatableCTE SET NextLp=NULL
WHERE Nr=1;

SELECT * FROM @tbl;

您可以先使用可更新的CTE将数字放置到行中,然后再更新您要定位的数字。

更新

结果

ProductID   PriceID NextLp
APPLE       1       -
APPLE       2       -
APPLE       3       NULL
PEAR        1       -
PEAR        2       NULL

在上面的示例中,将两行设置为NULL。两行都是其组中的最高价格ID ...

ROW_NUMBER()a window functionOVER()-clause允许PARTITION BY在集合内创建组,而ORDER BY将对组进行排序,在这种情况下,将按PriceID降序排列。这会将1绑定到每一行,其中PriceIDProductID组中是最高的。

提示:您可以使用SELECT * FROM UpdatableCTE代替UPDATE语句。这将向您显示编号的行,并允许检查编号。