Sql server 逐案订购
我有以下SQL脚本:Sql server 逐案订购,sql-server,sql-order-by,case,Sql Server,Sql Order By,Case,我有以下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 [R
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;
orderby
中的前两个案例有多个列可供排序
当我尝试保存脚本时,它会给我以下消息:
Msg 169,第15级,状态1,程序getRequests,第8行在“排序依据”列表中多次指定了列。排序依据列表中的列必须是唯一的
如何确保列是唯一的?您应该将逻辑从使用复杂的
ORDER BY
列列表更改为使用IF
子句并指定多个select语句和ORDER BY
s
比如:
如果您必须使用以下用例,则可能会得到类似的结果:
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
同样,您可能不想这样做。并且性能可能会受到影响 我建议您使用这种类型的存储过程:
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
问题在于
OrgCountVote
字段。CASE
语句中包含的字段很好。。。至少,它在我的测试系统(SQLServer2008R2)上运行良好。即便如此,我还是建议在每个案例条件中添加一个defaultELSE
子句,您还应该知道,这可能会导致一些非常糟糕的查询计划(糟糕的性能)。对于这种情况,在客户机代码中进行排序将获得更好的性能
也就是说,你可以像这样完成你需要的:
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
我需要解释一下日期(最新优先)
条目。如果只执行一个简单的datediff,则最终会溢出整数类型。该长表达式的所有其余部分只是将日期字段转换为一个数字,您可以将其乘以-1,从而反转排序顺序。如何做到这一点归功于此链接:
如果您不需要毫秒级粒度(即:您只存储日期值,时间组件中全是零),或者如果您不在乎,那么这里和那里都不是完美的(几乎同时出现的记录可能会出错,如果您的数据很少出现这种情况的话),然后,您可以大大简化该表达式,只需计算自unix纪元以来的秒数或自Sql Server纪元以来的分钟数或天数。我想出了一种相当动态的方法来按顺序进行操作。在我下面的示例中,我可以添加任意数量的WHEN's,它只需一步一步地遍历它们并获取相关语句
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;
我不必担心ELSE,因为参数有一个默认值分配给它,因此始终会有以下语句之一:
@SortBy VARCHAR(50) = 'Status'
你必须用IF子句重写整个SQL语句,以便按照你的要求进行排序。你只需要一个“case”和一个“end”。Tim,它给了我相同的错误消息。很抱歉,没有看到你按顺序排列其他case。解决了它!问题在于前两种情况下的柱组合是相同的。我删除了第二个案例中的第二列,还有viola!它是有效的。这样做的原因是为了减少错误地忽略较大SQL语句中的更改的可能性(为了说明我的问题,我将代码缩减为可管理的块。实际SP有149行长,已经有4条IF语句)。如果我没有第二次约会的话,这个案子就完美了。
@SortBy VARCHAR(50) = 'Status'