Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/25.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql server 逐案订购_Sql Server_Sql Order By_Case - Fatal编程技术网

Sql server 逐案订购

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

我有以下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;
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)上运行良好。即便如此,我还是建议在每个案例条件中添加一个default
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
我需要解释一下
日期(最新优先)
条目。如果只执行一个简单的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'