我编写了一个存储过程,它根据用户选择的列返回已排序(升序或降序)数据。 为实现这一点,我在 order by order 中使用了案例陈述,如下面的代码片段
ORDER BY
CASE WHEN p_filter_type = 'ASC' THEN
CASE p_filter_column
WHEN 'projectCode' THEN projectCode -- varchar field
WHEN 'visaType' THEN visaType -- varchar field
WHEN 'approveRejectStatus' THEN `status` -- varchar field
WHEN 'createdDate' THEN createdDate
WHEN 'employeeID' THEN employeeId -- int field
WHEN 'requestId' THEN requestId -- int field
WHEN 'country' THEN country -- varchar field
WHEN 'serviceDesk' THEN serviceDesk -- varchar field
END
END,
CASE WHEN p_filter_type = 'DESC' THEN
CASE p_filter_column
WHEN 'projectCode' THEN projectCode -- varchar field
WHEN 'visaType' THEN visaType -- varchar field
WHEN 'approveRejectStatus' THEN `status` -- varchar field
WHEN 'createdDate' THEN createdDate
WHEN 'employeeID' THEN employeeId -- int field
WHEN 'requestId' THEN requestId -- int field
WHEN 'country' THEN country -- varchar field
WHEN 'serviceDesk' THEN serviceDesk -- varchar field
END
END DESC
此代码中的问题是它不会正确排序数据(如果有的话) 选择具有整数数据类型的列。 它将整数值视为varchar并相应地对数据进行排序
例如 它返回
10
1
2
3
如果在 ASCENDING 顺序中选择 requestId 。
我尝试使用几个解决方案解决问题,例如使用ABS()将varchar值转换为整数等,但它们并没有帮我解决问题。
如果你们帮助我解决问题,我将不胜感激
答案 0 :(得分:2)
实际上,当您组合不同的数据类型时,即使 p_filter_type 和 p_filter_column 指示只有数字列,表达式也会转换为varchar
应该确定该表达的结果。
解决此问题的一种方法是为每种可能性创建单独的order by
表达式,为所有这些表达式生成null
,除了相关的表达式。这样每个表达式都可以坚持自己的数据类型:
ORDER BY
CASE WHEN p_filter_type = 'ASC' AND p_filter_column = 'projectCode'
THEN projectcode END ASC,
CASE WHEN p_filter_type = 'ASC' AND p_filter_column = 'visaType'
THEN visaType END ASC,
CASE WHEN p_filter_type = 'ASC' AND p_filter_column = 'approveRejectStatus'
THEN status END ASC,
CASE WHEN p_filter_type = 'ASC' AND p_filter_column = 'createdDate'
THEN createdDate END ASC,
CASE WHEN p_filter_type = 'ASC' AND p_filter_column = 'employeeID'
THEN employeeID END ASC,
CASE WHEN p_filter_type = 'ASC' AND p_filter_column = 'requestId'
THEN requestId END ASC,
CASE WHEN p_filter_type = 'ASC' AND p_filter_column = 'country'
THEN country END ASC,
CASE WHEN p_filter_type = 'ASC' AND p_filter_column = 'serviceDesk'
THEN serviceDesk END ASC,
CASE WHEN p_filter_type = 'DESC' AND p_filter_column = 'projectCode'
THEN projectcode END DESC,
CASE WHEN p_filter_type = 'DESC' AND p_filter_column = 'visaType'
THEN visaType END DESC,
CASE WHEN p_filter_type = 'DESC' AND p_filter_column = 'approveRejectStatus'
THEN status END DESC,
CASE WHEN p_filter_type = 'DESC' AND p_filter_column = 'createdDate'
THEN createdDate END DESC,
CASE WHEN p_filter_type = 'DESC' AND p_filter_column = 'employeeID'
THEN employeeID END DESC,
CASE WHEN p_filter_type = 'DESC' AND p_filter_column = 'requestId'
THEN requestId END DESC,
CASE WHEN p_filter_type = 'DESC' AND p_filter_column = 'country'
THEN country END DESC,
CASE WHEN p_filter_type = 'DESC' AND p_filter_column = 'serviceDesk'
THEN serviceDesk END DESC
例如,当p_filter_type = 'DESC'
和p_filter_column = 'employeeID'
时,上述ORDER BY
条款确实解析为以下内容:
ORDER BY
NULL ASC,
NULL ASC,
NULL ASC,
NULL ASC,
NULL ASC,
NULL ASC,
NULL ASC,
NULL ASC,
NULL DESC,
NULL DESC,
NULL DESC,
NULL DESC,
employeeID DESC,
NULL DESC,
NULL DESC,
NULL DESC
应该像你刚刚写的那样订购:
ORDER BY
employeeID DESC
当然,你可以选择一个中间解决方案,在这个解决方案中,将一个表达式中具有相同数据类型的字段组合在一起,这样就不会发生数据类型转换。这样,您的order by
子句中可能有6个表达式:一个用于varchar
个字段,一个用于int
字段,一个用于date
字段,然后每个都重复对于降序案例:
ORDER BY
CASE WHEN p_filter_type = 'ASC' THEN
CASE p_filter_column -- all varchar fields
WHEN 'projectCode' THEN projectCode
WHEN 'visaType' THEN visaType
WHEN 'approveRejectStatus' THEN status
WHEN 'country' THEN country
WHEN 'serviceDesk' THEN serviceDesk
END
END ASC,
CASE WHEN p_filter_type = 'ASC' THEN
CASE p_filter_column -- all int fields
WHEN 'employeeID' THEN employeeId
WHEN 'requestId' THEN requestId
END
END ASC,
CASE WHEN p_filter_type = 'ASC' THEN
CASE p_filter_column -- all date fields
WHEN 'createdDate' THEN createdDate
END
END ASC,
CASE WHEN p_filter_type = 'DESC' THEN
CASE p_filter_column -- all varchar fields
WHEN 'projectCode' THEN projectCode
WHEN 'visaType' THEN visaType
WHEN 'approveRejectStatus' THEN status
WHEN 'country' THEN country
WHEN 'serviceDesk' THEN serviceDesk
END
END DESC,
CASE WHEN p_filter_type = 'DESC' THEN
CASE p_filter_column -- all int fields
WHEN 'employeeID' THEN employeeId
WHEN 'requestId' THEN requestId
END
END DESC,
CASE WHEN p_filter_type = 'DESC' THEN
CASE p_filter_column -- all date fields
WHEN 'createdDate' THEN createdDate
END
END DESC
答案 1 :(得分:0)
如何将ASC订单添加到第一个案例?
SELECT b.*
FROM B b
WHERE b.id = a.id
AND b.modified_date > a.modified.date
有用吗?此外,您确定您用作错误排序示例的日期不在Varchar列中吗?它看起来像一个人一样。
答案 2 :(得分:0)
如果你只想将varchar值转换为整数,假设这些值是数字,mysql可以简单地做到,让这个列加0,如下所示:
ORDER BY
CASE WHEN p_filter_type = 'ASC' THEN
CASE p_filter_column
WHEN 'projectCode' THEN projectCode -- varchar field
WHEN 'visaType' THEN visaType -- varchar field
WHEN 'approveRejectStatus' THEN `status` -- varchar field
WHEN 'createdDate' THEN createdDate
WHEN 'employeeID' THEN employeeId -- int field
WHEN 'requestId' THEN requestId + 0 -- int field
WHEN 'country' THEN country -- varchar field
WHEN 'serviceDesk' THEN serviceDesk -- varchar field
END
END,
CASE WHEN p_filter_type = 'DESC' THEN
CASE p_filter_column
WHEN 'projectCode' THEN projectCode -- varchar field
WHEN 'visaType' THEN visaType -- varchar field
WHEN 'approveRejectStatus' THEN `status` -- varchar field
WHEN 'createdDate' THEN createdDate
WHEN 'employeeID' THEN employeeId -- int field
WHEN 'requestId' THEN requestId + 0 -- int field
WHEN 'country' THEN country -- varchar field
WHEN 'serviceDesk' THEN serviceDesk -- varchar field
END
END DESC
在sqlfiddle中查看简单的demo。
答案 3 :(得分:0)
ORDER BY
CASE WHEN p_filter_type = 'ASC' THEN
CASE p_filter_column
WHEN 'projectCode' THEN CAST(projectCode AS INT) -- varchar field
WHEN 'visaType' THEN CAST(visaType AS INT) -- varchar field
WHEN 'approveRejectStatus' THEN CAST(status AS INT) -- varchar field
WHEN 'createdDate' THEN createdDate
WHEN 'employeeID' THEN employeeId -- int field
WHEN 'requestId' THEN requestId -- int field
WHEN 'country' THEN CAST(country AS INT) -- varchar field
WHEN 'serviceDesk' THEN CAST(serviceDesk AS INT) -- varchar field
END
END,
CASE WHEN p_filter_type = 'DESC' THEN
CASE p_filter_column
WHEN 'projectCode' THEN CAST(projectCode AS INT) -- varchar field
WHEN 'visaType' THEN CAST(visaType AS INT) -- varchar field
WHEN 'approveRejectStatus' THEN CAST(status AS INT) -- varchar field
WHEN 'createdDate' THEN createdDate
WHEN 'employeeID' THEN employeeId -- int field
WHEN 'requestId' THEN requestId -- int field
WHEN 'country' THEN CAST(country AS INT) -- varchar field
WHEN 'serviceDesk' THEN CAST(serviceDesk AS INT) -- varchar field
END
END DESC
我认为由于varchar类型的列包含数字,并且您希望根据数字对此字段进行排序,因此您需要在排序期间将该VARCHAR字段转换为INT,就像我在上面的代码中尝试过的那样。 希望这会对你有所帮助。
答案 4 :(得分:0)
由于CASE
返回原子值,因此返回的数据类型只能是单个。在不同的执行中,您不能具有不同的返回数据类型。在这种情况下,所有内容都被隐式转换为varchar。为了获得您想要的订单,您必须确保整数将根据字符串排序规则进行排序。像这样:
CASE WHEN p_filter_type = 'ASC' THEN
CASE p_filter_column
WHEN 'projectCode' THEN projectCode -- varchar field
WHEN 'visaType' THEN visaType -- varchar field
WHEN 'approveRejectStatus' THEN `status` -- varchar field
WHEN 'createdDate' THEN createdDate
WHEN 'employeeID' THEN RIGHT(CONCAT('00', employeeId), 2) -- int field
WHEN 'requestId' THEN RIGHT(CONCAT('00', requestId), 2) -- int field
WHEN 'country' THEN country -- varchar field
WHEN 'serviceDesk' THEN serviceDesk -- varchar field
END
END
对于排序,它会将值更改为01, 02, 03, 10
,这将按您希望的方式排序。
我不确定您的日期是否会被正确订购,这取决于您当地的设置。
答案 5 :(得分:0)
您可以使用CONCAT函数生成预准备语句:
SET @sql = CONCAT('select * from some_table order by ', p_filter_column, ' ', p_filter_type);
PREPARE stmt FROM @sql;
EXECUTE stmt;
作为奖励,预备语句可以使用索引(如果已定义)。
但是,您可能需要先验证输入。
另一种解决方法可能是将LPAD用于数字字段并用零填充数字:
WHEN 'employeeID' THEN LPAD(employeeId, 20, '0') -- int field
但它只适用于UNSIGNED类型。