MySql排序工作异常

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语句,就像下面的代码片段一样

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
是一个INT
requestId+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了,这工作非常好:)非常感谢!