我使用一个存储过程来尝试从一个排序的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查询( @startRow和@endRow之间的RowNumber ),但没有成功。
发布于 2012-07-10 08:46:05
你可以这样做:
;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中获得更好的性能(如果启用了optimize for ad hoc workloads设置,它将不会受到上述解决方案中固有的参数嗅探问题的影响,也不会计划缓存膨胀):
DECLARE @sql NVARCHAR(MAX);
SET @sql = N';WITH Ordering AS
(
SELECT ROW_NUMBER() OVER (ORDER BY ' + @SortBy + ' '
+ @SortDirection + ') 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
ORDER BY RowNumber;';
EXEC sp_executesql @sql,
N'@username NVARCHAR(50), @startRow INT, @endRow INT',
@username, @startRow, @endRow;发布于 2012-07-10 08:46:40
您的问题是在查询中使用常量。您正在按常量字符串而不是列进行排序。我认为您混淆了动态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。我认为这需要两个查询,这是可行的,因为这是在存储过程中。
我喜欢Aaron的回答,但我认为它可以改进。
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()调用,它有一个更复杂的排序表达式。除了实际用于排序的值之外,所有的值都将为空。
https://stackoverflow.com/questions/11405091
复制相似问题