我正在尝试使用以下查询进行排序:
SELECT * FROM client
ORDER BY
CASE $desired_colum_to_order
WHEN 'id' then `id`
WHEN 'name' then `name`
ELSE `id`
END
ASC
问题是此查询将ID作为字符串列进行排序,但它是整数主键。
结果按此顺序排列: 10,11,12,13,5,6,7,8,9
如果我执行以下查询,MySQL会正确排序:
SELECT * FROM client
ORDER BY
id
ASC
现在结果按正确顺序排列: 5,6,7,8,9,10,11,12,13
有人可以解释一下,为什么MySQL这样排序,如果两个查询中的列相同吗?
提前致谢!
答案 0 :(得分:1)
您可以将order by
拆分为不同的条件:
SELECT *
FROM client
ORDER BY (CASE WHEN $desired_colum_to_order = 'id' then id END) ASC,
(CASE WHEN $desired_colum_to_order = 'name' then name END) ASC,
id ASC
这是有效的,因为case
语句不匹配所有返回NULL
,没有订单。如果没有匹配,那么最终的id
将是使用的那个。不同case
语句的优点是每列都是“类型”安全的。此外,您可以使用逻辑来制作一些DESC
而不是ASC
。
答案 1 :(得分:1)
问题是CASE
表达式变成了字符串,因为该数据类型是MySQL发现的最常见的数据类型。
一个选项是将case语句拆分为所有可用的列,如下所示:
ORDER BY
CASE $orderColumn = 'id' THEN id ELSE 0 END
, CASE $orderColumn = 'name' THEN name ELSE '' END
另一种选择是像这样对数字字段进行zerofill:
ORDER BY
CASE $desired_colum_to_order
WHEN 'id' then LPAD(CONVERT(`id`,VARCHAR(20)),20,'0')
WHEN 'name' then `name`
ELSE `id`
END
或者(我认为这是最好的选择):在您的应用程序中构建查询以动态添加所需的ORDER BY
子句
答案 2 :(得分:1)
您的个案陈述:
CASE $desired_colum_to_order
WHEN 'id' then `id`
WHEN 'name' then `name`
ELSE `id`
END
是字符串类型的表达式 - >串。唯一的选择是字符串 - > int,但是应该如何将name解释为int?你可以做的是将你的比较分成两部分:
ORDER BY CASE $desired_colum_to_order WHEN 'name' then `name` else '' end
, CASE $desired_colum_to_order WHEN 'id' then `id` else 0 end
第一个CASE是表达式字符串 - > string,第二个是表达式字符串 - > INT。不相关的CASE会将所有值映射到该类型的标识元素,因此不会影响排序。
答案 3 :(得分:0)
CASE
将结果评估为字符串。要获得所需的结果,您可以尝试:
SELECT *
FROM client
ORDER BY
CASE $desire_column_to_order
WHEN 'name' THEN `name`
ELSE 0
END ASC,
`id` ASC
答案 4 :(得分:0)
问:有人可以解释一下为什么MySQL会这样订购吗?
MySQL是"订购"基于ORDER BY子句中表达式的结果的行。
您在ORDER BY子句中提供了CASE
表达式。该表达式返回单个数据类型。在这种情况下,表达式似乎返回 VARCHAR
,可能基于name
列的数据类型。
优化器不够智能"找出'id'
关键字后面的字符串文字CASE
总是与第一个'id'
后面的字符串文字WHEN
匹配。你看到了,但优化器没有。
你读了那个表达式,你看到第一个WHEN
将匹配每一行,表达式总是返回id
,表达式永远不会返回name
您认为这等同于指定ORDER BY id
。
但是优化器并没有这样看待它。它将name
视为可能的返回值,并且它基于"工作的数据类型"对于所有可能的返回值。在这种情况下,看起来它确定VARCHAR
是要返回的适当数据类型。
如果CASE表达式中的返回数据类型为整数,则行将按升序数值排序。
但MySQL仍然无法使用索引按顺序返回行,它仍然会执行"使用filesort"操作,因为行仍然按表达式的结果排序,而不是列。