我在SQL中有以下脚本:
ALTER PROC [dbo].[getRequests]
@SortBy VARCHAR(50) = 'Date'
AS
SELECT [ReqDate], [RequestorOrg], [RequestCategory],
[ReqDescription], [OrgCountVote]
ORDER BY
CASE WHEN @SortBy = 'Date (oldest first)' THEN [ReqDate] END ASC, [OrgCountVote] DESC,
CASE WHEN @SortBy = 'Date (newest first)' THEN [ReqDate] END DESC, [OrgCountVote] ,
CASE WHEN @SortBy = 'Number of Votes' THEN [OrgCountVote] END DESC, reqdate,
CASE WHEN @SortBy = 'Organisation' THEN [RequestorOrg] END,
CASE WHEN @SortBy = 'Category' THEN [RequestCategory] END;
ORDER BY
中的前两个案例有多个要排序的列。
当我尝试保存脚本时,它会给我以下消息:
Msg 169,Level 15,State 1,Procedure getRequests,Line 8
已按列表顺序多次指定列。按列表排列的列必须是唯一的。
如何确保列是唯一的??
答案 0 :(得分:4)
我建议你使用这种类型的存储过程:
ALTER PROC [dbo].[getRequests]
@SortBy VARCHAR(50) = 'Date'
AS
BEGIN
DECLARE @sql varchar(max)
SET @sql = 'SELECT [ReqDate], [RequestorOrg], [RequestCategory], [ReqDescription], [OrgCountVote] ' +
'ORDER BY ' +
CASE @SortBy
WHEN 'Date (oldest first)' THEN '[ReqDate] ASC, [OrgCountVote] DESC'
WHEN 'Date (newest first)' THEN '[ReqDate] DESC, [OrgCountVote] '
WHEN 'Number of Votes' THEN '[OrgCountVote] DESC, reqdate'
WHEN 'Organisation' THEN '[RequestorOrg]'
WHEN 'Category' THEN '[RequestCategory]'
END
EXEC(@sql)
END
答案 1 :(得分:1)
问题是OrgCountVote
字段。 CASE
语句中包含的字段很好......至少,它在我的测试系统(Sql Server 2008 R2)上运行良好。即便如此,我建议为每个案例条件添加一个默认的ELSE
子句,你也应该知道这可能导致一些非常糟糕的查询计划(性能不佳)。对于这种情况,您可以在客户端代码中获得更多更好的性能。
那就是说,你可以像这样完成你需要的东西:
ORDER BY
--first level
CASE WHEN @SortBy = 'Date (oldest first)' THEN [ReqDate]
WHEN @SortBy = 'Date (newest first)' THEN CAST(CAST([ReqDate]-'1970-01-01' AS decimal(38,10))*-24*60*60*1000+0.5 as bigint)
WHEN @SortBy = 'Number of Votes' THEN [OrgCountVote] * -1
WHEN @SortBy = 'Organisation' THEN [RequestorOrg]
WHEN @SortBy = 'Category' THEN [RequestCategory] END,
--second level
CASE WHEN @SortBy = 'Date (oldest first)' THEN [OrgCountVote] * -1
WHEN @SortBy = 'Date (newest first)' THEN [OrgCountVote]
WHEN @SortBy = 'Number of Votes' THEN reqdate
ELSE NULL END
我需要暂时解释Date (newest first)
条目。如果你只是做一个简单的约会,你最终会溢出整数类型。该长表达式的所有其余部分只是将日期字段转换为可以乘以-1的数字,从而反转排序顺序。相信这个链接是如何做到的:
如果你不需要毫秒粒度(即:你只存储日期值,时间组件中全为零)或者你不关心它在这里和那里都不完美(几乎同时记录)如果你的数据非常罕见,那么可能会出现故障,那么你可以大大简化那个表达式,然后只考虑自unix时代以来的秒数或者自上次以来的分钟数或天数。 Sql Server时代。
答案 2 :(得分:0)
您应该将逻辑从使用复杂的ORDER BY
列列表更改为使用IF
子句并指定多个select语句和ORDER BY
。
像:
If @SortBy = 'Date....' then
Begin
-- SQL with the single order by group...
End
Else if @SortBy =... Then...
Begin
End
答案 3 :(得分:0)
如果您必须使用案例,这可能会给您类似的结果:
ALTER PROC [dbo].[getRequests]
@SortBy VARCHAR(50) = 'Date'
AS
SELECT [ReqDate], [RequestorOrg], [RequestCategory],
[ReqDescription], [OrgCountVote]
FROM requests
ORDER BY
CASE
WHEN @SortBy = 'Date (oldest first)' THEN Datediff(day, '2010-1-1', [ReqDate])
WHEN @SortBy = 'Date (newest first)' THEN [ReqDate]
WHEN @SortBy = 'Number of Votes' THEN [RequestorOrg]
WHEN @SortBy = 'Category' THEN [RequestCategory]
END DESC,
CASE WHEN @SortBy = 'Date (newest first)' THEN OrgCountVote
WHEN @SortBy = 'Number of Votes' THEN [OrgCountVote]
ELSE '' END
同样,你可能不想这样做。并且可以实现性能。
答案 4 :(得分:0)
我想出了一个动态的ORDER BY方式。在我下面的例子中,我可以添加尽可能多的WHEN,它只是单步执行它们并获取相关的语句。
~s({"start_usage":"0","left_operand":"2"})
|> Poison.Parser.parse!
|> Map.get("left_operand")
|> String.to_integer()
我不必担心ELSE,因为参数具有分配给它的默认值,因此将始终具有以下语句之一:
ORDER BY
CASE WHEN @SortBy = 'Date (oldest first)' THEN [ReqDateTime] END ASC,
CASE WHEN @SortBy = 'Date (oldest first)' THEN [OrgCountVote] END DESC,
CASE WHEN @SortBy = 'Date (newest first)' THEN [ReqDateTime] END DESC,
CASE WHEN @SortBy = 'Date (newest first)' THEN [OrgCountVote] END DESC,
CASE WHEN @SortBy = 'Number of Votes' THEN [OrgCountVote] END DESC,
CASE WHEN @SortBy = 'Number of Votes' THEN [ReqDateTime] END DESC,
CASE WHEN @SortBy = 'Organisation' THEN [RequestorOrg] END,
CASE WHEN @SortBy = 'Status' THEN ReqStatus END,
CASE WHEN @SortBy = 'Category' THEN [RequestCategory] END;