【问题标题】:Finding Maximum value from a Varchar Field从 Varchar 字段中查找最大值
【发布时间】:2010-12-20 17:24:25
【问题描述】:

我有一个名为 SCORES 的数据库字段,其中包含分数 该值可能如下所示

123

14

56*

342

423*

我将其存储在数据库的 Varchar 字段中。

假设如果我将它转换为整数数据类型,那么我可以写 max(SCORES) 并获得最高分或最高分。 但是整数不允许像 * 这样的特殊字符。

(这里*代表该分数的一些子句)

为了适应我对 varchar 所做的。

用最少的编程方法很容易获得最高分的最佳方法是什么。

所以如果我执行一个查询,我应该得到答案

423*

请给我建议

【问题讨论】:

    标签: php database-design mysql


    【解决方案1】:

    处理这种情况的最好方法是改变你的表结构以使

    • SCORESint 数据类型。
    • 在表中添加一个名为 clause
    • 如果您的大部分SCORES 都没有 clause,你必须规范化表格 将clause 字段移动到 不同的表。

    【讨论】:

    • 如果我这样做,将会有大量的数据输入工作,因为我有将近 60000 行需要获取数据。
    • 在你找到解决方案之前应该考虑到这一点
    • 现在正试图以最好的方式摆脱它
    【解决方案2】:

    您应该更改表架构 ...

    SELECT scores
    FROM tablename
    ORDER BY replace(scores, '*', '') DESC
    LIMIT 1;
    

    【讨论】:

    • @harigm - 上述查询将准确返回423*。您应该更改列以确保优化得到重视
    • 表示需要更改列类型?如果这真的适用于 100 万条记录,那就太棒了,请让我清楚地做并测试它
    • @harigm - 您可以复制一个没有星号的额外列,并在该列上添加一个索引,始终使用该列进行排序,同时您仍然可以使用原始列显示使用结果(带星号)
    【解决方案3】:

    我认为您的查询应该是通用的以获得最高分数,今天您只有 '*' 附加了分数,但将来您可能会使用其他一些字符,或者您可能会使用一些字符组合,所以您应该小心那个场景。

    所以如果你创建一个用户定义函数会更好,它接受 varchar 作为输入并从输入字符串返回数字,如果你传递 '1234*' 那么函数将返回 1234,如果你传递 1234** 它将返回 1234。

    CREATE FUNCTION dbo.ParseNumeric
    (
      @string VARCHAR(8000)
    )
    RETURNS VARCHAR(8000)
    AS
    BEGIN
      DECLARE @IncorrectCharLoc SMALLINT
      SET @IncorrectCharLoc = PATINDEX('%[^0-9A-Za-z]%', @string)
      WHILE @IncorrectCharLoc > 0
      BEGIN
        SET @string = STUFF(@string, @IncorrectCharLoc, 1, '')
        SET @IncorrectCharLoc = PATINDEX('%[^0-9]%', @string)
      END
      SET @string = @string
      RETURN @string
    END
    GO
    

    然后使用:

    select max(cast(dbo.ParseNumeric(score) as int)) from tableName
    

    【讨论】:

    • 虽然这样的东西可以工作,但效果会很差。唯一真正的解决方案是修复糟糕的表格设计。
    【解决方案4】:
    SELECT MAX(CAST(scores AS SIGNED))
      FROM tablename
    

    但是这个查询会很慢,因为它不能使用索引进行优化。

    【讨论】:

    • 这可行,但会给你一个警告'截断不正确的整数值:'11*'
    【解决方案5】:

    您可以将星号移动到新字段(取决于您是否需要)。之后,您可以更改数据类型。

    UPDATE
        tableName
    SET
        score = REPLACE(score, '*', ''),
        specialCharField = IF(CONTAINS(score, '*'), '*', '');
    

    【讨论】:

      【解决方案6】:

      试试这个 SQL:

      SELECT MAX(CONVERT(REPLACE(FIELD,'*',''),signed)) FROM TABLE
      

      它:

      • 替换 varchar 中的 *
      • 将结果转换为整数(有符号)
      • 选择最大值

      编辑 1:

      我一直在用一些数据来处理 SQL,我有一个包含一个字段(varchar,无键)的表,我插入了 62962 个值(每 1000 个有一个'*',结果如下 :)

      SELECT MAX(CONVERT(REPLACE(FIELD,'*',''),signed)) FROM TABLE
      

      耗时 0.0666 秒。

      SELECT scores FROM tablename ORDER BY replace(scores, '*', '') DESC LIMIT 1;
      

      执行耗时 0.089 秒,得到了错误的值:

      HTH :)

      【讨论】:

      • 100万条记录执行查询怎么样,会不会很贵
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-10-12
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多