如何在存储过程的参数中指定要排序的列?

时间:2011-12-17 18:08:41

标签: sql sql-server stored-procedures

我有一个存储过程来从表中返回前50行,如下所示:

select top 50 
    Puzzle, 
    min(DateSolved) as CreationDate, 
    avg(SecondsToComplete) as AverageTime, 
    count(*) as TimesSolved 
  from CustomSolves
  group by Puzzle

但我希望存储过程接受两个参数,以便我可以通过自定义列(创建日期,平均时间或所覆盖的时间)进行排序,并且只选择比特定日期更新的记录。像这样的伪SQL:

procedure SelectCustomPuzzles
  @CutoffDate datetime,
  @SortColumn column
as
  select top 50 
      Puzzle, 
      min(DateSolved) as CreationDate, 
      avg(SecondsToComplete) as AverageTime, 
      count(*) as TimesSolved 
    from CustomSolves
    where CreationDate > @CutOffDate
    group by Puzzle
    order by @SortColumn

我怎么能做这样的事情?

3 个答案:

答案 0 :(得分:4)

order by 
   CASE @SortColumn WHEN 'foo ASC' THEN foo ELSE NULL END,
   CASE @SortColumn WHEN 'foo DESC' THEN foo ELSE NULL END DESC,
   CASE @SortColumn WHEN 'bar ASC' THEN bar ELSE NULL END,
   CASE @SortColumn WHEN 'bar DESC' THEN bar ELSE NULL END DESC,

编辑,对于默认排序,添加其中一个

...
CASE  WHEN @SortColumn IS NULL THEN default ELSE NULL END DESC

...
defautcolumn

注意:

  • ASC或DESC无法进入CASE:必须在外面
  • 具有多个WHEN..THEN column的单个CASE要求数据类型隐式为CASTable。我更喜欢使用单独的CASE表达式来避免隐式转换。请参阅https://dba.stackexchange.com/a/4166/630了解实例

答案 1 :(得分:2)

您可以使用case

order by case when @SortColumn = 'Puzzle' then Puzzle end,
         case when @SortColumn = 'PuzzleDesc' then Puzzle end desc,
         ...

如果您编写此类查询,则数据库无法使用索引。唯一的方法是动态SQL,如:

declare @sql nvarchar(max)
set @sql = 'select * from tbl1 order by ' + @OrderByVar
exec @sql

答案 2 :(得分:2)

除非您愿意进入动态SQL领域(对order by之类的东西可能有些过分),否则请考虑使用case-when

order by case(@SortColumn)
    when 'ColumnName2' then ColumnName1
    when 'ColumnName2' then ColumnName2
    else ColumnName3
end

正如gbn在下面提到的,这只会因为您的三个列的类型相同而有效。如果不是这样,你需要添加一个演员(可能是sql_variant),以便SQL服务器接受你的查询。