0

对于具有可配置排序顺序(_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并且distanceDOUBLE

但如果 _Sort = 1,则按CHARuid排序,例如

200
207
 25
  4

同样的事情distance。转换为无符号和十进制没有帮助。

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

任何的想法?

4

2 回答 2

1

控制流功能下所述:

表达式的返回类型CASE是所有返回值的兼容聚合类型

虽然该手册没有明确记录“兼容的聚合类型”是如何确定的,但可以从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 的字符串;然后从该字符串准备并执行一条语句:

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;
于 2013-03-06T08:22:47.070 回答
0

试试这个解决方案(已编辑) -

SELECT * FROM distances
ORDER BY
  IF(_Sort = 1, uid, 0),
  IF(_Sort = 2, NULL, 0),
  IF(_Sort = 3, name, 0),
  IF(_Sort = 4, NULL, 0),
  ...
于 2013-03-06T07:47:41.577 回答