【问题标题】:MySQL Order By Case Casting Tinyint to StringMySQL 按大小写顺序将 Tinyint 转换为字符串
【发布时间】:2015-03-04 16:25:17
【问题描述】:

我有以下疑问:

SELECT
    id,
    display_order
FROM 
    data_element_value
WHERE 
       key_id = 32
ORDER BY 
    CASE WHEN (display_order IS NOT NULL) THEN 
        display_order
    ELSE 
        `value` 
    END

预期的输出是:

id                    display_order
1                     1
13                    2
15                    3
16                    10

但是,我得到:

id                    display_order
1                     1
16                    10
13                    2
15                    3

我已经尝试将display_order 转换为UNSIGNED

CASE WHEN (display_order IS NOT NULL) THEN
    CAST(display_order as UNSIGNED)
ELSE
    `VALUE`
END

我也试过了:

CASE WHEN (display_order IS NOT NULL) THEN
    display_order + 0
ELSE
    `VALUE`
END

但这似乎没有帮助。

对于display_order,列数据类型为tinyint(2), unsigned, and allow nulls

编辑

这里是describe data_element_value

Field           Type                Null    Key Default Extra
id              int(11)             NO      PRI (null)  auto_increment
key_id          int(11)             NO      MUL (null)  
value           varchar(50)         NO          (null)  
sub_title       varchar(125)        YES         (null)  
chart_color     char(7)             YES         (null)  
display_order   tinyint(2) unsigned YES         (null)  

我可以做些什么来纠正这个问题吗?

【问题讨论】:

  • describe data_element_value 的输出是什么?
  • 您可以发布您的表格示例吗?使用相同的行测试解决方案会很有趣
  • @cegfault 我添加了描述

标签: mysql sql-order-by case


【解决方案1】:

CASE 中所述:

CASE 表达式的返回类型是所有返回值的兼容聚合类型,但也取决于使用它的上下文。如果在字符串上下文中使用,结果将作为字符串返回。如果在数字上下文中使用,则结果以小数、实数或整数值形式返回。

由于您的value 列是字符串类型,您必须单独使用CAST 或者value 列,或者整个CASE 表达式,才能达到您想要的结果。在这种情况下,COALESCE() 也会比CASE 更简洁:

SELECT
    id,
    display_order
FROM 
    data_element_value
WHERE 
    key_id = 32
ORDER BY 
    COALESCE(display_order, CAST(`value` AS UNSIGNED))

【讨论】:

  • update - 这就像一个魅力(有点)。它不在 value 列上排序,仅在 display_order 列上排序。
  • @GreenChili:对于那些应该使用display_order IS NULLvalue 的记录......这不是你想要的吗?您的意思是先按display_order 排序,然后在具有匹配display_order 的记录中按value 排序?如果是这样,您只需要ORDER BY display_order, `value`
  • 不一定先按 display_order 排序,然后按值排序。如果 display_order 不为 null,我希望按 display_order 排序,如果 display_order 为 null,则按值(可以是任何字符串值)排序。从查看 WonderCricket 的回复,到现在您的评论。看来只需一个简单的“按 display_order,值排序”就可以了。
  • @GreenChili:假设您有以下(display_id, value) 记录—(1,1), (1,3), (2,1), (NULL,2);应该按什么顺序退回?
  • 如果我有以下 (id, display_order, value) 记录 - (1, 1, 'b'), (2, 2, 'a'), (3, null, 'b' ), (4, null, 'a')。它将返回(按 id):1、2、4、3
【解决方案2】:

您可以使用简单的order by 而不使用casecoalesce 语句,它会正常工作。

SELECT
    id,
    display_order
FROM 
    data_element_value
WHERE 
       key_id = 32
ORDER BY `display_order`, `value`

【讨论】:

  • 您正在对问题中未给出的 OP 的预期业务逻辑进行假设。然而,考虑到the recent comment to my answer,这可能确实是真正想要的。
猜你喜欢
  • 2017-05-18
  • 2014-06-17
  • 2014-03-30
  • 2010-11-15
  • 1970-01-01
相关资源
最近更新 更多