简体   繁体   English

根据另一列 Sql 服务器中给出的公式更新表中的列

[英]Update a column in table based on formula given in another column Sql Server

I have a table with 4 columns:我有一个有 4 列的表:

Col1  Col2      Col3       Col4
1      2      Col1+Col2     3
3      4      Col1*Col2     12
6      3      Col1/Col2     2

Col1, Col2 and would have some values, col3 would have a formula and based on that formula I need to populate values in col4. Col1, Col2 会有一些值,col3 会有一个公式,基于该公式我需要在 col4 中填充值。 I have tried it using dynamic SQL which works row by row but I have millions of records in my table and it is taking forever to execute the script.我已经尝试使用动态 SQL 逐行工作,但我的表中有数百万条记录,并且执行脚本需要很长时间。 Please suggest the simplest and fastest way to handle this scenario.请提出处理这种情况的最简单和最快的方法。

You could write an update query for each operator if you only have a single operator in the column +,-,/,*如果在 +,-,/,* 列中只有一个运算符,则可以为每个运算符编写更新查询

Depending on the distribution of the data solving the simple operations first in bulk, will speed up the process根据数据的分布,首先批量解决简单的操作,将加快处理速度


-- Bulk operation for Col1 * Col2
UPDATE Table
    Set Col4 = Col1 * Col2
WHERE LEN(Col4) - LEN(REPLACE(Col4, '*', '')) = 1 -- Only has one *
AND Like 'Col1%'
AND Like '%Col2'
-- Doesn't have other operator
AND NOT LIKE '%+%'
AND NOT LIKE '%*%'
AND NOT LIKE '%/%'

You could generate these queries using T4 if you have multiple columns/combinations.如果您有多个列/组合,则可以使用T4生成这些查询。

For multiple operators you will need a parser because you need to take care or order of operators and other rules.对于多个运算符,您将需要一个解析器,因为您需要注意运算符和其他规则的顺序。

This is one of the (very) rare cases where a cursor is appropriate.这是 cursor 适合的(非常)罕见的情况之一。 In fact, this is rather complicated -- an updatable cursor along with dynamic SQL.事实上,这相当复杂——一个可更新的 cursor 以及动态 SQL。

Here is the idea:这是想法:

declare @col1 int;
declare @col2 int;
declare @col3 nvarchar(max);
declare @sql nvarchar(max);
declare @col4 int;


DECLARE c CURSOR
FOR SELECT col1, col2, col3 FROM t FOR UPDATE;

OPEN c;

FETCH NEXT FROM c INTO @col1, @col2, @col3;

WHILE @@fetch_status = 0
BEGIN
    set @sql = 'select @col4=[col3] from (select @col1 as col1, @col2 as col2) t';
    
    set @sql = replace(@sql, '[col3]', @col3);
    
    exec sp_executesql @sql, N'@col1 int, @col2 int, @col4 int output',
                       @col1=@col1, @col2=@col2, @col4=@col4 output;

    SELECT @col1, @col2, @col3, @col4;
    
    UPDATE t
        set col4 = @col4
        WHERE current of c;
    
    FETCH NEXT FROM c INTO @col1, @col2, @col3;
END;

CLOSE c;
DEALLOCATE c;

And here is a db<>fiddle. 是一个 db<>fiddle。

Note that this will not be speedy.请注意,这不会很快。 Getting performance on such a query is quite difficult, but you can break the table up into chunks and update each chunk using a separate thread.在这样的查询上获得性能是相当困难的,但是您可以将表分成块并使用单独的线程更新每个块。

You can change your approach and work in set based mode, using also programming language as C#您可以更改方法并在基于集合的模式下工作,也可以使用编程语言 C#

With running total query you can calculate the distribution of your data and work with chunk of x records to update by Col3.通过运行总查询,您可以计算数据的分布并使用 x 记录块以通过 Col3 更新。 In order not to have lock escalation I advise to work with 1000 rows at a time.为了不进行锁升级,我建议一次使用 1000 行。 Example for running total query:运行总查询的示例:

https://codingsight.com/calculating-running-total-with-over-clause-and-partition-by-clause-in-sql-server/ https://codingsight.com/calculating-running-total-with-over-clause-and-partition-by-clause-in-sql-server/

Now, you can update Col4 with equal chunk (calculated before) using Col3 as condition in a C# cycle or other programming languages (you can also use a while loop in SQL but it isn't recommended)现在,您可以在 C# 循环或其他编程语言中使用 Col3 作为条件更新 Col4 等块(之前计算)(您也可以在 SQL 中使用 while 循环,但不推荐)

PS check your indexes before to run the procedure PS 在运行该过程之前检查您的索引

If the expressions in col3 are syntactically correct in a way SQL server can understand and execute them, you can use dynamic SQL.如果col3中的表达式在语法上正确,SQL 服务器可以理解并执行它们,则可以使用动态 SQL。 Create a query with a CASE expression.使用CASE表达式创建查询。 In the case expression, every branch checks for the string value of col3 and returns the respective expression.在 case 表达式中,每个分支都会检查col3的字符串值并返回相应的表达式。 You just need as many branches as there are distinct expressions.您只需要与不同表达式一样多的分支。

DECLARE @query nvarchar(MAX);

SELECT @query = concat('UPDATE elbat', nchar(13), nchar(10),
                       '       SET col4 = CASE', nchar(13), nchar(10),
                       (SELECT DISTINCT
                               concat('                    WHEN col3 = ''', col3, '''', nchar(13), nchar(10),
                                      '                      THEN ', col3, nchar(13), nchar(10)) [text()]
                               FROM elbat
                               FOR XML PATH(''),
                                       TYPE).value('.', 'nvarchar(max)'),
                       '                  END;')
       WHERE EXISTS (SELECT *
                            FROM elbat);

PRINT @query;

EXEC(@query);

db<>fiddle db<>小提琴

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 SQL Server更新列基于另一个表中的值 - SQL Server Update Column based on value from another table 基于另一个表的SQL更新列 - SQL update column based on another table SQL Server:根据同一表中另一列与另一表的列的匹配值,更新一个表中的列的值 - SQL Server: update value of a column in one table based on the matching value of another column in the same table to another table's column 基于存储在另一列中的SQL的SQL Server更新列 - SQL Server Update Column based on SQL stored in another column 在 MS SQL Server 中需要搜索一列中的多个字符串并根据搜索更新表中的另一列 - In MS SQL Server Need to search multiple strings in a column and update another column in a table based on search SQL Server-选择要基于另一个列值进行更新的列 - SQL Server - Select column to update based on another column value 根据另一个表中与第一个表中的列名相关的值,更新一个表中的SQL Server表值 - Update SQL Server table values in one table based upon values in another table that relate to the column names in the first 根据两个列值是否出现在SQL Server 2008 R2的另一个表中来更新表 - Update a table based on if two column values appear in another table on SQL Server 2008 R2 Oracle SQL根据另一个表但根据日期更新列 - Oracle SQL Update a column based on another table but based on a date 基于另一个表中的公式的列计算 - Column calculation based on formula from another Table
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM