Sql 具有多列的动态按选择排序

Sql 具有多列的动态按选择排序,sql,sql-server,Sql,Sql Server,当ORDER BY基于CASE语句时,选择多个ORDER BY列的正确MS SQL语法是什么 以下内容适用于单列,但我需要按多列排序: SELECT * FROM Products ORDER BY CASE WHEN @SortIndex = 1 THEN Price END ASC, CASE WHEN @SortIndex = 2 THEN Price DESC, Title ASC END <-- problem line 你可以试试这个 SELECT * FROM Produ

当ORDER BY基于CASE语句时,选择多个ORDER BY列的正确MS SQL语法是什么

以下内容适用于单列,但我需要按多列排序:

SELECT * FROM Products
ORDER BY 
CASE WHEN @SortIndex = 1 THEN Price END ASC,
CASE WHEN @SortIndex = 2 THEN Price DESC, Title ASC END <-- problem line
你可以试试这个

SELECT * FROM Products
ORDER BY 
CASE WHEN @SortIndex = 1 THEN Price END ASC,
CASE WHEN @SortIndex = 2 THEN Price END DESC, 
CASE WHEN @SortIndex = 2 THEN Title END ASC 

做这个。。。和你的表演说再见。不幸的是,最好的解决方案是使用动态sql。

尝试使用动态sql,以降低对服务器性能的影响-假设@SortIndex 1和2处只有2个值。如果没有,请使用更多条件扩展If

If @SortIndex = 1   
BEGIN
    SELECT * FROM Products ORDER BY Price ASC   
END
ELSE
BEGIN
    SELECT * FROM Products ORDER BY Price DESC, TITLE ASC 
END

@布拉德。帕维尔提出了以下建议,我想

DECLARE @query VARCHAR(MAX)

SET @query = 'SELECT * FROM Products 
              ORDER BY  
              '

IF (@SortIndex = 1) 
    SET @query =@query  + ' Price ASC '
ELSE IF (@SortIndex = 2) 
    SET @query =@query  + ' Price DESC, Title ASC '

sp_executesql @query

为什么您认为动态sql不适合复杂的存储过程?这些正是您应该使用动态SQL的地方,因为它可以帮助降低复杂性并解决诸如参数嗅探之类的问题。我同意动态sql有其缺点,但我建议您至少尝试一下,如果它适合您的话。

您可以重写以下内容:

ORDER BY 
CASE WHEN @SortIndex = 1 THEN Price END ASC,
CASE WHEN @SortIndex = 2 THEN Price DESC, Title ASC END
作为

这会将添加的排序列添加到所有案例中,但在我的情况下,这正是我想要的

您也可以这样做,例如:

CASE WHEN @SortIndex = 1 THEN Price END ASC,Title ASC,
CASE WHEN @SortIndex = 2 THEN Price DESC END

想详细说明一下吗?我在一个相当复杂的存储过程中实际应用了它,在这个过程中,动态SQL是不可能的。在我使用MSSQL的12年经验中,我遇到了多个ocation,这些构造产生了糟糕的计划。这并不是说它本身不好,只是我发现它不可靠,即今天运行良好的查询可能会在未来4个月产生糟糕的计划我在这里嗅到参数:。。此解决方案实际上可能会引入参数嗅探,假设这是一个存储过程,@SortIndex是存储过程的一个参数。为了便于讨论,我们假设还有另一个条件——如果@SortIndex=3,那么只按平铺排序,假设有一个价格指数和一个标题指数。现在,如果您第一次使用@SortIndex=1调用存储过程,SQL server将创建一个exec计划,该计划将使用价格索引。再次调用存储过程时,无论@SortTitle的值是多少,SQL server都将使用与以前相同的计划。因此,如果@SortTitle=3,它仍将使用价格索引,即使它在这里没有用处,我从未假设这是一个存储过程。如果它是一个简单的SQL语句,具有变量声明和变量属性值,那么查询应该有一个良好的执行计划,这取决于它将使用哪个叶。用户没有说这是一个只有一个参数的存储过程;如果真的是这样的话,考虑到为每个组合检索的行数,可以启用或禁用参数嗅探。谢谢您的建议。我将尝试这种方法。查询越复杂,尤其是那些具有多个输入、多个排序选择等的可怕列表过程,您从动态SQL获得的结果就越可靠。我这里唯一的建议是保护您的动态查询免受注入攻击。对于我的特殊问题,我使用了Price END ASC,而不是Price END DESC,因为我们必须从数据库中的同一列加载排序列。所以为了使它干净,我们用空格分隔每一列,并用负号代替DESCI投票赞成yrushka的答案。这是一个有效的选择。但在我的例子中,我使用了上面的方法,用户有12个可能的列进行排序,因此这种样式/选项看起来更实用。如果我添加查询语句本身非常复杂的话,我上面的评论会更有意义。在这种情况下,用不同的orderby条款重复整个station 12次是不切实际的。
CASE WHEN @SortIndex = 1 THEN Price END ASC,Title ASC,
CASE WHEN @SortIndex = 2 THEN Price DESC END