MySql排序工作异常
我编写了一个存储过程,它根据用户选择的列返回排序(升序或降序)数据。 为了实现这一点,我在我的order by子句中使用了Case语句,就像下面的代码片段一样MySql排序工作异常,mysql,sql,Mysql,Sql,我编写了一个存储过程,它根据用户选择的列返回排序(升序或降序)数据。 为了实现这一点,我在我的order by子句中使用了Case语句,就像下面的代码片段一样 ORDER BY CASE WHEN p_filter_type = 'ASC' THEN CASE p_filter_column WHEN 'projectCode' THEN projectCode -- varchar field WHEN 'visaTy
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
如果按升序选择requestId
我尝试使用两种解决方案来解决这个问题,比如使用ABS()将varchar值转换为整数等,但它们并没有帮助我解决这个问题
如果你们能帮我解决这个问题,我将不胜感激将ASC订单添加到第一个案例中如何
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 ASC,
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列中吗?它看起来就像一个。如果您只想将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中的一个简单示例
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,正如我在上述代码中尝试的那样。
希望这能对您有所帮助。因为
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
,这将按照您希望的方式进行排序
不过,我不确定您的日期是否会被正确排序,这取决于您的本地设置。您可以使用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
但它只适用于无符号类型。事实上,当您组合不同的数据类型时,表达式将转换为
varchar
,即使p_filter_type和p_filter_column指示只有数值列才能确定该表达式的结果
解决这个问题的一种方法是为每个可能性创建一个单独的orderby
表达式,为所有可能性生成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\u filter\u type='DESC'
和p\u filter\u 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
所有涉及的varchar字段是否仅由数字组成?看起来它将所有内容都按字符串排序,您可以尝试强制转换为int@RafalZiolkowski,这就是OP写的和做的。一种方法是生成一个脚本。我将使用准备好的语句尝试它。我尝试将ASC添加到其中。但是它给出了相同的输出,顺便说一句,sql默认按ASC顺序排序,如果
requestId
是一个INTrequestId+0
,则不会改变任何内容。@Dhananjaysakare参见演示,您最好在op.No中发布一些示例数据,varchar字段将包含字母数字值,例如,projectCode将包含类似“e.00031234”的内容,approveRejectStatus将包含待定、已批准、已拒绝等。因此,当“requestId”被强制转换时,您只能尝试使用(requestId为INT)--int field
与此列一起。可能这会解决您的问题。当您尝试使用CASE进行排序时,当时,它会自动将字段转换为VARCHAR
@SagarGangwal,我知道,但这不会有帮助,它会将int
转换为int
,然后仍然是一个varchar
。参考我的答案。我认为只需要两组。首先是数字类型(使用+0
再次将case语句转换为数字),然后是所有其他类型。我刚刚在回答中添加了一个类似的解决方案,仍然为date
数据类型保留了一个单独的表达式,但它可能与int
组合。注意/当CASE
语句中的THEN/ELSE
表达式都是int
时,就不需要+0
@trincot了,这工作非常好:)非常感谢!