0

让我们称之为测试

 ----------------------------
 |  id  |  catid  |  value  |
 |  1   |    1    |   1     |
 |  2   |    1    |   2     |
 |  3   |    2    |   1     |
 |  4   |    1    |   3     |
 |  5   |    1    |   4     |
 |  6   |    1    |   5     |
 |  7   |    2    |   2     |
 ----------------------------

假设我从表中删除了第二行。现在表格将变为:

 ----------------------------
 |  id  |  catid  |  value  |
 |  1   |    1    |   1     |
 |  3   |    2    |   1     |
 |  4   |    1    |   3     |
 |  5   |    1    |   4     |
 |  6   |    1    |   5     |
 |  7   |    2    |   2     |
 ----------------------------

所以在 中catid1,没有值 2。所以值将变为 1,3,4,5,.... 到目前为止......

目标我需要将这些值更新为从它们以前的值中减去 1,以便保持连续性(如果满足条件,即如果比删除的值更高,则所有值都会上升)。

代码 删除后,我正在尝试执行更新查询。

UPDATE     `test` 
SET        `value` = 
      (

         SELECT t.param FROM (

                         SELECT `value`-1 AS  param
                         FROM `test`
                         WHERE          
                         `catid` = 1 AND `value` > 2

                       ) AS t

       ) 
WHERE 
      `catid` = 1
      AND   `value` > 2 

现在,最内部的查询将返回值 >2 的所有行,因为更新需要字符串或数字的标量值。

所以问题是我如何在最里面的查询中返回关于更新查询目标的行的值?

例如,如果更新查询尝试更新 id 为 4 的行,则最内层查询将value检索具有相同行 id 的列并将其返回给外部查询(减去 1 后)。

这有什么替代方法吗?

4

1 回答 1

1

JOIN带有这个子查询的表是这样的:

UPDATE test t1
INNER JOIN
( 
  SELECT 
    id, catid, value - 1 AS value
  FROM test
  WHERE catid = 1
    AND value > 2
) AS t2 ON t1.id = t2.id
SET t1.value = t2.value;

SQL 小提琴演示

但是不需要这个子查询,你可以直接这样做:

UPDATE test t1
SET value = value - 1
WHERE catid = 1
  AND value > 2;

但是,您可能需要修复该列id以匹配这些值,如下所示:

UPDATE test AS t1
INNER JOIN
(
  SELECT 
    *, 
    (@rownum := @rownum + 1) AS newID
  FROM test, (SELECT @rownum := 0) AS t
  ORDER BY Id
) AS t2 ON t1.id = t2.id
SET t1.id = t2.newId,
    t1.value = CASE 
                 WHEN t1.catid = 1 AND t1.value > 2 THEN t2.value - 1 
                 ELSE t1.value 
               END;

更新了 SQL Fiddle 演示

于 2013-02-02T07:58:23.907 回答