Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/api/5.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查询进行排序_Sql_Sql Server 2008_Stored Procedures - Fatal编程技术网

使用存储过程对行限制SQL查询进行排序

使用存储过程对行限制SQL查询进行排序,sql,sql-server-2008,stored-procedures,Sql,Sql Server 2008,Stored Procedures,我正在使用一个存储过程尝试从排序的SQL查询中获取前几行,其中输入参数指定要检索的行数和排序条件 我已经能够正确地检索前几行,但是当我尝试对结果进行排序时,它们只是使用默认条件(主键)进行排序 所以我想知道是否有人可以看一下 USE [database] GO SET ANSI_NULLS OFF GO SET QUOTED_IDENTIFIER OFF GO ALTER PROCEDURE [dbo].[x0] @username nvarchar(50), @sortBy varchar(

我正在使用一个存储过程尝试从排序的SQL查询中获取前几行,其中输入参数指定要检索的行数和排序条件

我已经能够正确地检索前几行,但是当我尝试对结果进行排序时,它们只是使用默认条件(主键)进行排序

所以我想知道是否有人可以看一下

USE [database]
GO
SET ANSI_NULLS OFF
GO
SET QUOTED_IDENTIFIER OFF
GO
ALTER PROCEDURE [dbo].[x0] 
@username nvarchar(50),
@sortBy varchar(50),
@sortDirection varchar(4),
@startRow int,
@endRow int

AS
With Ordering AS(

    SELECT ROW_NUMBER() OVER (Order by
        CASE    WHEN @sortBy='datecreate' THEN 'datecreate'
                WHEN @sortBy='id' THEN 'id'
                WHEN @sortBy='DisplayName' THEN 'DisplayName'
        END,
        CASE    WHEN @sortDirection='asc' THEN 'asc'
                WHEN @sortDirection='desc' THEN 'desc'
        END) AS RowNumber,

    dbo.x1.*, dbo.x2.* 
    FROM  dbo.x1 INNER JOIN dbo.x2 ON dbo.x1.type = dbo.x2.type
    where username = @username
)
SELECT     RowNumber, *, DisplayName AS DisplayName
FROM         Ordering
Where RowNumber BETWEEN @startRow AND @endRow 

我还尝试将排序条件移动到外部SQL查询(其中RowNumber介于@startRow和@endRow之间),但运气不好。

您可以这样做:

;WITH Ordering AS
(
   SELECT rnd  = ROW_NUMBER() OVER (ORDER BY datecreate),
          rni  = ROW_NUMBER() OVER (ORDER BY id),
          rnn  = ROW_NUMBER() OVER (ORDER BY DisplayName),
          rndd = ROW_NUMBER() OVER (ORDER BY datecreate DESC),
          rnid = ROW_NUMBER() OVER (ORDER BY id DESC),
          rnnd = ROW_NUMBER() OVER (ORDER BY DisplayName DESC),
    dbo.x1.*, dbo.x2.* 
    FROM dbo.x1 INNER JOIN dbo.x2 ON dbo.x1.type = dbo.x2.type
    where username = @username
),
x AS 
(
  SELECT RowNumber = CASE @SortDirection 
    WHEN 'asc' THEN CASE @SortBy
      WHEN 'datecreate'   THEN rnd
      WHEN 'id'           THEN rni
      WHEN 'DisplayName'  THEN rnn 
    END
    WHEN 'desc' THEN CASE @sortBy
      WHEN 'datecreate'   THEN rndd
      WHEN 'id'           THEN rnid
      WHEN 'DisplayName'  THEN rnnd
    END, *, DisplayName AS DisplayName
  FROM Ordering
)
SELECT * FROM x
WHERE RowNumber BETWEEN @startRow AND @endRow 
ORDER BY RowNumber;
但老实说,我认为动态SQL会带来更好的性能(如果启用了
optimizeforad hoc workload
设置,则不会出现上述解决方案中固有的参数嗅探问题或计划缓存膨胀):


你可以这样做:

;WITH Ordering AS
(
   SELECT rnd  = ROW_NUMBER() OVER (ORDER BY datecreate),
          rni  = ROW_NUMBER() OVER (ORDER BY id),
          rnn  = ROW_NUMBER() OVER (ORDER BY DisplayName),
          rndd = ROW_NUMBER() OVER (ORDER BY datecreate DESC),
          rnid = ROW_NUMBER() OVER (ORDER BY id DESC),
          rnnd = ROW_NUMBER() OVER (ORDER BY DisplayName DESC),
    dbo.x1.*, dbo.x2.* 
    FROM dbo.x1 INNER JOIN dbo.x2 ON dbo.x1.type = dbo.x2.type
    where username = @username
),
x AS 
(
  SELECT RowNumber = CASE @SortDirection 
    WHEN 'asc' THEN CASE @SortBy
      WHEN 'datecreate'   THEN rnd
      WHEN 'id'           THEN rni
      WHEN 'DisplayName'  THEN rnn 
    END
    WHEN 'desc' THEN CASE @sortBy
      WHEN 'datecreate'   THEN rndd
      WHEN 'id'           THEN rnid
      WHEN 'DisplayName'  THEN rnnd
    END, *, DisplayName AS DisplayName
  FROM Ordering
)
SELECT * FROM x
WHERE RowNumber BETWEEN @startRow AND @endRow 
ORDER BY RowNumber;
但老实说,我认为动态SQL会带来更好的性能(如果启用了
optimizeforad hoc workload
设置,则不会出现上述解决方案中固有的参数嗅探问题或计划缓存膨胀):


您的问题是在查询中使用常量。您是按常量字符串排序,而不是按列排序。我认为您将动态SQL和常规SQL混为一谈

要获取名称,您需要使用:

SELECT ROW_NUMBER() OVER (Order by
        CASE    WHEN @sortBy='datecreate' THEN datecreate
            WHEN @sortBy='id' THEN id
            WHEN @sortBy='DisplayName' THEN DisplayName
        END,
但是,由于类型冲突,这将不起作用。你有两个选择。首先,将所有类型转换为具有正确排序顺序的字符串(日期为YYYY-MM-DD,数字为零填充)。或者,因为这是一个存储过程,所以为每个过程创建一个单独的查询

问题是您可能将所有内容都作为字符串获取,但我仍然不确定如何将ASC和DESC获取。我认为这需要两个查询,这是可行的,因为这是在一个存储过程中

我喜欢亚伦的回答,但我认为可以改进

WITH Ordering AS (
   SELECT ROW_NUMBER() OVER
                 (ORDER BY (case when @sortBy = 'datecreate' and @sortdirection = 'ASC'
                                 then datecreate
                            end),
                           (case when @sortBy = 'datecreate' and @sortdirection = 'DESC'
                                 then datecreate
                            end) desc,
                           (case when @sortBy = 'id' and @sortdirection = 'ASC'
                                 then id
                            end),
                           (case when @sortBy = 'id' and @sortdirection = 'DESC'
                                 then id
                            end) desc,
                           (case when @sortBy = 'DisplayName' and @sortdirection = 'ASC'
                                 then DisplayName
                            end),
                           (case when @sortBy = 'DisplayName' and @sortdirection = 'DESC'
                                 then DisplayName
                            end) desc
                 ) as rn,
          dbo.x1.*, dbo.x2.*
   FROM dbo.x1 INNER JOIN dbo.x2 ON dbo.x1.type = dbo.x2.type
   where username = @username
)

等等。不同之处在于,只有一个row_number()调用,具有更复杂的排序表达式。除实际用于排序的值外,所有值都将为空。

您的问题是在查询中使用常量。您是按常量字符串排序,而不是按列排序。我认为您将动态SQL和常规SQL混为一谈

要获取名称,您需要使用:

SELECT ROW_NUMBER() OVER (Order by
        CASE    WHEN @sortBy='datecreate' THEN datecreate
            WHEN @sortBy='id' THEN id
            WHEN @sortBy='DisplayName' THEN DisplayName
        END,
但是,由于类型冲突,这将不起作用。你有两个选择。首先,将所有类型转换为具有正确排序顺序的字符串(日期为YYYY-MM-DD,数字为零填充)。或者,因为这是一个存储过程,所以为每个过程创建一个单独的查询

问题是您可能将所有内容都作为字符串获取,但我仍然不确定如何将ASC和DESC获取。我认为这需要两个查询,这是可行的,因为这是在一个存储过程中

我喜欢亚伦的回答,但我认为可以改进

WITH Ordering AS (
   SELECT ROW_NUMBER() OVER
                 (ORDER BY (case when @sortBy = 'datecreate' and @sortdirection = 'ASC'
                                 then datecreate
                            end),
                           (case when @sortBy = 'datecreate' and @sortdirection = 'DESC'
                                 then datecreate
                            end) desc,
                           (case when @sortBy = 'id' and @sortdirection = 'ASC'
                                 then id
                            end),
                           (case when @sortBy = 'id' and @sortdirection = 'DESC'
                                 then id
                            end) desc,
                           (case when @sortBy = 'DisplayName' and @sortdirection = 'ASC'
                                 then DisplayName
                            end),
                           (case when @sortBy = 'DisplayName' and @sortdirection = 'DESC'
                                 then DisplayName
                            end) desc
                 ) as rn,
          dbo.x1.*, dbo.x2.*
   FROM dbo.x1 INNER JOIN dbo.x2 ON dbo.x1.type = dbo.x2.type
   where username = @username
)

等等。不同之处在于,只有一个row_number()调用,具有更复杂的排序表达式。除实际用于排序的值外,所有值都将为空。

一旦正确应用了内部行号(),则仍需要对外部查询执行
按行号排序。
一旦正确应用了内部行号(),您仍然需要在外部查询中按行编号排序。ASC/DESC可以这样处理。我相信你可以在别处找到更多的细节。当@sortDirection='ASC'CASE@@sortBy当'X'时,X当'Y'时,Y当'Z'时,Z结束,否则空结束ASC,CASE WHEN@@sortDirection='DESC'CASE@@sortBy WHEN'X'然后X WHEN'Y'然后Y WHEN'Z'然后Z END ELSE NULL ENDDESC@GordonLinoff我同意优先考虑限制排序,但随着排列的增加,查询的可维护性绝对是一场噩梦。事实上,我要详细说明的是,至少在本例中,动态SQL可能是更好的选择—无论是在可维护性方面还是在性能方面。ASC/DESC可以这样处理。我相信你可以在别处找到更多的细节。当@sortDirection='ASC'CASE@@sortBy当'X'时,X当'Y'时,Y当'Z'时,Z结束,否则空结束ASC,CASE WHEN@@sortDirection='DESC'CASE@@sortBy WHEN'X'然后X WHEN'Y'然后Y WHEN'Z'然后Z END ELSE NULL ENDDESC@GordonLinoff我同意优先考虑限制排序,但随着排列的增加,查询的可维护性绝对是一场噩梦。事实上,我这么详细说明的目的是要说明,至少在本例中,动态SQL可能是更好的选择—无论是在可维护性还是性能方面。