我有一个存储过程来从表中返回前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
我怎么能做这样的事情?
答案 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
注意:
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服务器接受你的查询。