在表格中向下移动值

Mah*_*ahn 6 php mysql

如果我从mysql数据库表中得到以下结果集:

+----+------+-------+
| ID | type | value |
+----+------+-------+
|  8 |    A |  1435 |
|  9 |    B |  7348 | 
| 10 |    A |  1347 | 
| 11 |    A |  3478 | 
| 12 |    A |  4589 | 
| 13 |    B |  6789 |
+----+------+-------+
Run Code Online (Sandbox Code Playgroud)

我想删除行ID 8并将字段'value'中的值向下推,这样每行都有前一个条目的值,但只影响字段'type'与行相同的那些行被删除(在这种情况下为'A').

也就是说,删除行id 8最终应该产生以下结果:

+----+------+-------+
| ID | type | value |
+----+------+-------+
|  - |    - |    -  | *
|  9 |    B |  7348 |   |
| 10 |    A |  1435 | * |
| 11 |    A |  1347 | * |
| 12 |    A |  3478 | * |
| 13 |    B |  6789 |   V
+----+------+-------+
Run Code Online (Sandbox Code Playgroud)

ID 10继承了ID 8的值,然后ID 11继承自ID 10,依此类推.但请注意,类型为"B"的行不受影响.

所以问题是:有没有办法在不必逐个查询和更新每一行的情况下执行值的"移位"?在理想的世界中,我会做一个查询来做移位,然后另一个查询来删除行,但我不确定这是否可行.

(另外我宁愿不使用触发器,因为我打算将所有应用程序逻辑封装在应用程序本身中)

egg*_*yal 2

SET @remove_id = 8;

SELECT ID, type, value FROM (
  SELECT   ID,
           type,
           CAST(IF(type <> @type OR ISNULL(@val), value, @val) AS UNSIGNED)
             AS value,
           @type := IF(ID   = @remove_id, type, @type),
           @val  := IF(type = @type, value, @val)
  FROM     my_table JOIN (SELECT @type := NULL, @val := NULL) AS z
  ORDER BY ID ASC
) AS t
WHERE ID <> @remove_id
Run Code Online (Sandbox Code Playgroud)

在sqlfiddle上查看它。


更新

我没有意识到您实际上想要更新基础表。为此,您可以使用一些轻微的技巧在UPDATE语句中有效地执行相同的操作(不能直接分配给用户变量,因此可以将其新值和从第一个值形成的空字符串的串联分配给列)新分配的用户变量的 0 个字符):

SET @remove_id = 8, @type = NULL, @val = NULL;

UPDATE my_table SET
  value = IF(
    type <> @type OR ISNULL(@val),
    value,
    CONCAT(@val, LEFT(@val := value, 0))
  ),
  type = CONCAT(type, LEFT(
    @type := IF(
      ID <> @remove_id,
      @type,
      CONCAT(type, LEFT(@val := value, 0))
    )
  , 0))
ORDER BY ID ASC;

DELETE FROM my_table WHERE ID = @remove_id;
Run Code Online (Sandbox Code Playgroud)

在sqlfiddle上查看它。