【问题标题】:Update float column but retain its decimal - resequence an index to remove gaps更新浮点列但保留其小数 - 重新排序索引以消除间隙
【发布时间】:2015-03-05 11:54:15
【问题描述】:

我有一张这样的桌子:

name     |   index
item A   |   1
item B   |   3
item C   |   3.2
item D   |   3.3
item E   |   30
item F   |   30.1

如何使用 mysql 或 php 对索引列重新排序以删除整数序列中的所有间隙,以便表格如下所示:

name     |   index
item A   |   1
item B   |   2
item C   |   2.2
item D   |   2.3
item E   |   3
item F   |   3.1

我尝试使用 SUBSTRING 仅替换索引中的第一个数字,但这不允许项目 E 和 F

【问题讨论】:

  • "like this" - 显示一个示例不是正确的描述 - 特别是如果您没有列出所有边缘情况。
  • 鉴于您尝试执行的任务的性质,这些值似乎根本不是小数,而是由两个由. 字符分隔的整数组成,并且恰好被渲染为显示的分数。如果是这样,您可能明智地将值存储在两个单独的整数列中(如果需要,在应用程序的表示层将值组合成一个字符串)。当然,这并不能解决您的问题,但它至少开始将其简化为一个稍微简单的任务。
  • 是的,你是对的@eggyal - 最好将这些存储为单独的列,但是应用程序非常成熟,这是最后一个障碍,所以我想尝试解决它如果可能的话,在改写之前

标签: php mysql


【解决方案1】:

您可以使用user-defined variables 来跟踪上次看到的主要部分以及要替换的当前主要部分:

SET @new:=0, @old:=0;

UPDATE    myTable
SET      `index` = (@new := @new + (@old < (@old := `index` DIV 1))) + `index` MOD 1
ORDER BY `index`;

由内而外解释:

  • 要使用的变量首先初始化为零。

  • `index` DIV 1 给出当前index 值的整数部分;这被分配给@old,以便它可用于下一条记录。

  • 使用&lt;小于运算符将其与@old当前值(即来自上一个记录)进行比较;由于 MySQL 没有真正的布尔类型,这个表达式如果为真,则计算为 1,如果为假,则计算为 0——从而为递增 @new 提供了一个方便的快捷方式。

  • @new 更新为新的(即,如果合适,增加)值。

  • index 更新为 @new 加上 `index` MOD 1 的结果,这是原始 index 值的小数部分。

  • ORDER BY 子句确保更新以正确的顺序执行。

但是,鉴于您尝试执行的任务的性质,这些值似乎根本不是真正的小数,而是由两个由. 字符分隔的整数组成,并且只是发生呈现为分数以供显示。

如果是这样,您最好将值存储在两个单独的整数列中(如果需要,可以在应用程序的表示层将值组合成一个字符串)。

通过使用view 模拟旧表结构,可以提供迁移路径,而不会对现有代码库造成太多中断:

CREATE TABLE myNewTable LIKE myTable;

ALTER TABLE myNewTable
  ADD COLUMN index_major INT UNSIGNED NOT NULL,
  ADD COLUMN index_minor INT UNSIGNED NOT NULL;

INSERT INTO myNewTable
SELECT   myTable.*,
         @new := @new + (@old < (@old := `index` DIV 1)),
         CAST(SUBSTRING_INDEX(`index`, '.', -1) AS UNSIGNED)
FROM     myTable, (SELECT @new:=0, @old:=0) init
ORDER BY `index`;

ALTER TABLE myNewTable
  DROP COLUMN `index`;

ALTER TABLE myTable
  RENAME TO archived_myTable;

CREATE VIEW myTable AS
SELECT ..., CONCAT(index_major, '.', index_minor) AS `index` FROM myNewTable;

然后应用程序可以读取(并更新,除了合成的index 列)这个myTable 视图,就好像它是原始的myTable 一样——即在不知道已经发生的潜在变化的情况下。但是,INSERT 语句需要修改以使用新的底层 myNewTable

【讨论】:

猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-01-02
  • 1970-01-01
  • 1970-01-01
  • 2017-04-08
  • 2019-12-20
  • 2014-03-08
相关资源
最近更新 更多