简化表示电源组的表的UPDATE

时间:2012-03-10 18:33:27

标签: sql-server-2008 sql-update

我有2个表,我正在尝试用它来执行一些计算。我的第一个(基本上是'ABC'并且不包括NONE的功能集)表看起来像这样:

TABLE: test3
rowID    v1      v2      v3      combo    initialValue
1        NULL    NULL    M170_4  C        NULL
2        NULL    M170_3  NULL    B        NULL
3        NULL    M170_3  M170_4  BC       NULL
4        M170_2  NULL    NULL    A        NULL
5        M170_2  NULL    M170_4  AC       NULL
6        M170_2  M170_3  NULL    AB       NULL
7        M170_2  M170_3  M170_4  ABC      NULL

我需要更新每一行的initialValue列。

我有另一张这样的表:

TABLE: my_data_db
ID      WEIGHT    v1      v2      v3
1       1.34      0.10    NULL    NULL
2       0.53      0.75    NULL    0.75
3       1.24      0.25    0.10    0.25
4       0.95      NULL    1.00    0.10
5       0.72      0.75    NULL    0.10
6       0.145     1.00    1.00    0.75
...
AND SO ON

对于test3中的每一行,我需要计算my_data_db中相应行的乘积之和,如下所示:

DECLARE @total FLOAT
SET @total = 4898.947426

UPDATE test3 SET initialValue = 
(
    SELECT SUM(v3 * WEIGHT / @total) FROM my_data_db
)
WHERE combo = 'C'

UPDATE test3 SET initialValue = 
(
    SELECT SUM(v2 * WEIGHT / @total) FROM my_data_db
)
WHERE combo = 'B'

UPDATE test3 SET initialValue = 
(
    SELECT SUM(v2 * v3 * WEIGHT / @total) FROM my_data_db
)
WHERE combo = 'BC'


UPDATE test3 SET initialValue = 
(
    SELECT SUM(v1 * WEIGHT / @total) FROM my_data_db
)
WHERE combo = 'A'

UPDATE test3 SET initialValue = 
(
    SELECT SUM(v1 * v2 * WEIGHT / @total) FROM my_data_db
)
WHERE combo = 'AB'

UPDATE test3 SET initialValue = 
(
    SELECT SUM(v1 * v3 * WEIGHT / @total) FROM my_data_db
)
WHERE combo = 'AC'

UPDATE test3 SET initialValue = 
(
    SELECT SUM(v1 * v2 * v3 * WEIGHT / @total) FROM my_data_db
)
WHERE combo = 'ABC'

我无法弄清楚如何简化我的UPDATE,所以我不必每行更新一次。我上面的UPDATE代码虽然丑陋但并不算太多,但真正的问题是我会有类似于test3的表格,这些表格有超过一百万行,所有表格都有其独特的组合各栏目。另外,如果没有必要,我不想使用CURSORWHILE循环。使用CURSOR的解决方案(参见下面提到的上一篇文章)在我的电源设置表变大时无法扩展。

感谢。

(注意:以下是:Avoiding cursors to update many records using a trigger

1 个答案:

答案 0 :(得分:1)

以下是与您的一系列更新相同的计算,但使用单个语句。您可以看到此处未使用combo列。而是为两个表中的每一个生成一组新的列。新列在参与表和计算时都参与其中。

;
WITH
  test3_with_keys AS (
    SELECT
      RowID,
      key1 = CASE WHEN v1 IS NULL THEN 0 ELSE 1 END,
      key2 = CASE WHEN v2 IS NULL THEN 0 ELSE 1 END,
      key3 = CASE WHEN v3 IS NULL THEN 0 ELSE 1 END
    FROM @test3
  ),
  my_data_db_with_keys AS (
    SELECT
      WEIGHT,
      v1,
      v2,
      v3,
      key1 = CASE WHEN v1 IS NULL THEN 0 ELSE 1 END,
      key2 = CASE WHEN v2 IS NULL THEN 0 ELSE 1 END,
      key3 = CASE WHEN v3 IS NULL THEN 0 ELSE 1 END
    FROM @my_data_db
  ),
  calculated AS (
    SELECT
      t.RowID,
      initialValue = SUM(
        ISNULL(NULLIF(t.key1, 0) * d.v1, 1) *
        ISNULL(NULLIF(t.key2, 0) * d.v2, 1) *
        ISNULL(NULLIF(t.key3, 0) * d.v3, 1) *
        d.WEIGHT / @total
      )
    FROM test3_with_keys t
      INNER JOIN my_data_db_with_keys d ON t.key1 <= d.key1
                                       AND t.key2 <= d.key2
                                       AND t.key3 <= d.key3
    GROUP BY
      t.rowID
  )
UPDATE test3
SET initialValue = c.initialValue
FROM calculated c
WHERE test3.RowID = c.RowID;

注意:假设RowID值是唯一的。