在SQL Server中按多列排序

3
我在SQL Server中有一张表,需要按照某个值排序后选择数据。例如,
  • 如果排序值为1,则需要按照column1、column2和column3的顺序排序。

  • 如果排序值为2,则需要按照column2、column1和column3的顺序排序。

  • 如果排序值为3,则需要按照column3、column1和column2的顺序排序。

请问如何在SQL中实现这一功能而不使用if else语句呢?
IF @SortOrder = 1
THEN
    SELECT * 
    FROM table 
    ORDER BY c1, c2, c3
END

IF @SortOrder = 2
THEN
    SELECT * 
    FROM table 
    ORDER BY c2, c1, c3
END

IF @SortOrder = 3
THEN
    SELECT * 
    FROM table 
    ORDER BY c3, c1, c2
END

column1、column2和column3的数据类型是什么? - David Rushton
5个回答

4
您可以使用CASE表达式进行条件排序:
SELECT * FROM Table
ORDER BY CASE WHEN @SortOrder = 1 then c1
              WHEN @SortOrder = 2 then c2
              ELSE c3
         END,
         CASE WHEN @SortOrder = 1 then c2
              ELSE  c1
         END,
         CASE WHEN @SortOrder in(1,2) then c3
              ELSE c2
         END

我尝试了这个。但是由于我的第一列(c1)是日期类型,所以它会抛出一个错误,错误信息为“将日期和/或时间从字符字符串转换失败”。 - Bhavika
这根本不应该进行交谈,所以没有太多意义... 按日期列排序没有问题。@Bhavika - sagi
@sagi 我也在考虑写同样的东西。如果列类型冲突,这是行不通的。 - t-clausen.dk
当我将"else c1"部分放在第二个case语句中时,它显示了这个错误。 - Bhavika

4

使用CASE是正确的。如果列(c1、c2、c3)中的数据类型冲突,则需要使用此语法。

ORDER BY
  CASE WHEN @SortOrder = 1 THEN c1 END,
  CASE WHEN @SortOrder = 1 THEN c2 END,
  CASE WHEN @SortOrder = 1 THEN c3 END,
  CASE WHEN @SortOrder = 2 THEN c2 END,
  CASE WHEN @SortOrder = 2 THEN c1 END,
  CASE WHEN @SortOrder = 2 THEN c3 END,
  CASE WHEN @SortOrder = 3 THEN c3 END,
  CASE WHEN @SortOrder = 3 THEN c1 END,
  CASE WHEN @SortOrder = 3 THEN c2 END

这对我来说非常有效。非常感谢你。 :) - Bhavika

0
你可以在ORDER BY子句中使用CASE语句,并且用COALESCE函数来处理值。(请注意,你可能需要检查一下使用这种设置的性能。通常我没有问题,但是还是要提一下。)
SELECT *
FROM [TABLE]
ORDER BY
    CASE @SortOrder
    WHEN 1 THEN COALESCE(c1, N'') + N'-' + COALESCE(c2, N'') + N'-' + COALESCE(c3, N'')
    WHEN 2 THEN COALESCE(c2, N'') + N'-' + COALESCE(c1, N'') + N'-' + COALESCE(c3, N'')
    WHEN 3 THEN COALESCE(c3, N'') + N'-' + COALESCE(c1, N'') + N'-' + COALESCE(c2, N'')
        END

或者,如果你希望排序的值在结果中返回(但排序顺序列必须是第一列)

SELECT
    CASE @SortOrder
    WHEN 1 THEN COALESCE(c1, N'') + N'-' + COALESCE(c2, N'') + N'-' + COALESCE(c3, N'')
    WHEN 2 THEN COALESCE(c2, N'') + N'-' + COALESCE(c1, N'') + N'-' + COALESCE(c3, N'')
    WHEN 3 THEN COALESCE(c3, N'') + N'-' + COALESCE(c1, N'') + N'-' + COALESCE(c2, N'')
        END AS SortOrder
    *
FROM [TABLE]
ORDER BY 1

0
我认为在这里使用动态查询是最佳的条件排序方法。
DECLARE @sql       VARCHAR(max),
        @SortOrder INT = 2

SET @sql = 'select * from table order by ' 
            + CASE @SortOrder WHEN 1 THEN 'c1,c2,c3' WHEN 2 THEN 'c2,c1,c3' WHEN 3 THEN 'c3,c1,c2' END 

--print @sql
exec (@sql)

0
也许可以尝试这样做: select * from table order by @SortOrder,c1,c2,c3 如果该值代表列的顺序,否则你可以尝试添加一个偏移量(例如 @SortOrder + 4)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接