mysql ORDER BY 和 CASE 将 INT 转换为 CHAR?

标签 mysql casting sql-order-by

对于具有可配置排序顺序(_Sort 参数)的存储过程,我使用如下代码:

    SELECT * FROM distances   
    ORDER BY 
        CASE _Sort 
            WHEN 1 THEN uid
            WHEN 2 THEN NULL
            WHEN 3 THEN name
            WHEN 4 THEN NULL
            WHEN 5 THEN distance
            WHEN 6 THEN NULL
            ELSE distance
        END ASC,
        CASE _Sort 
            WHEN 2 THEN uid
            WHEN 4 THEN name
            WHEN 6 THEN distance
            ELSE NULL
        END DESC

其中uidINT距离DOUBLE

但是如果 _Sort = 1,uid 的排序就像 CHAR 一样,例如

200
207
 25
  4

对于距离也是如此。 转换为无符号和十进制没有帮助。

ORDER BY uid ASC 做正确的事情,即 4, 25, 200, 207

有什么想法吗?

最佳答案

Control Flow Functions 下所述:

The return type of a CASE expression is the compatible aggregated type of all return values

虽然手册没有明确记录如何确定“兼容聚合类型”,但可以遵循 Item_func_case::fix_length_and_dec() 的来源。通过agg_result_type()item_store_type() :

static Item_result item_store_type(Item_result a, Item *item,
                                   my_bool unsigned_flag)
{
  Item_result b= item->result_type();

  if (a == STRING_RESULT || b == STRING_RESULT)
    return STRING_RESULT;
  else if (a == REAL_RESULT || b == REAL_RESULT)
    return REAL_RESULT;
  else if (a == DECIMAL_RESULT || b == DECIMAL_RESULT ||
           unsigned_flag != item->unsigned_flag)
    return DECIMAL_RESULT;
  else
    return INT_RESULT;
}

因此可以看出,如果单个返回值是字符串,那么整个 CASE 表达式的返回值也将是字符串。

在您的情况下,人们假设 name 是一个字符串;因此,CASE 表达式返回的数据类型是字符串。因此,您的数值将作为字符串进行比较,从而按字典顺序排序(因此是您观察到的输出)。

克服这个问题的一种方法是将所有数值填充为相等的宽度,以便按字典顺序排序将提供所需的结果:使用整数类型列的 ZEROFILL 属性将自动执行此操作;但是,这仍然相当低效,您可能希望考虑重新设计您的逻辑。

例如,您可以构建一个包含所需 SQL 的字符串;然后prepare and execute该字符串的语句:

SET @sql := CONCAT(
  'SELECT * FROM distances ORDER BY ',
  CASE _Sort
    WHEN 1 THEN 'uid ASC'
    WHEN 2 THEN 'uid DESC'
    WHEN 3 THEN 'name ASC'
    WHEN 4 THEN 'name DESC'
    WHEN 5 THEN 'distance ASC'
    WHEN 6 THEN 'distance DESC'
    ELSE 'distance ASC'
  END
);

PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;

关于mysql ORDER BY 和 CASE 将 INT 转换为 CHAR?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15240355/

相关文章:

mysql - 使用 GROUP BY 时如何强制执行 ORDER BY?

mysql - 我可以将snort日志输出到数据库吗?

postgresql - 在 PostgreSQL 中转换为用户定义的数据类型

java - 按 ORMLite 中外部实体的属性排序

ruby-on-rails-3 - ActiveRecord查找全部不按ID排序吗?

sql-server - Order By 使用参数 varchar(100)

java - 错误 : in JAR with mysql-connector-java-5. 0.7-bin

mysql - SQL查询语句

typescript - 为什么 TypeScript 在分配给新的空数组时不暗示数组类型?

java - 在java中将整数数组转换为对象数组