我发现一个问题可以用 where 子句中的
Row_Number()
函数来回答。当我尝试一个查询时,我收到以下错误:
消息 4108 15 级状态 1 第 3 行
窗口函数只能出现在 SELECT 或 ORDER BY 子句中。
这是我尝试过的查询。如果有人知道如何解决这个问题,请告诉我。
SELECT employee_id
FROM V_EMPLOYEE
WHERE row_number() OVER (ORDER BY employee_id) > 0
ORDER BY Employee_ID
要解决此问题,请将 select 语句包装在 CTE 中,然后可以针对 CTE 进行查询并在 where 子句中使用窗口函数的结果。
WITH MyCte AS
(
select employee_id,
RowNum = row_number() OVER ( order by employee_id )
from V_EMPLOYEE
ORDER BY Employee_ID
)
SELECT employee_id
FROM MyCte
WHERE RowNum > 0
SELECT employee_id
FROM (
SELECT employee_id, ROW_NUMBER() OVER (ORDER BY employee_id) AS rn
FROM V_EMPLOYEE
) q
WHERE rn > 0
ORDER BY
Employee_ID
请注意,此过滤器是多余的:
ROW_NUMBER()
从1
开始,并且始终大于0
。
Select * from
(
Select ROW_NUMBER() OVER ( order by Id) as 'Row_Number', *
from tbl_Contact_Us
) as tbl
Where tbl.Row_Number = 5
我想你想要这样的东西:
SELECT employee_id
FROM (SELECT employee_id, row_number()
OVER (order by employee_id) AS 'rownumber'
FROM V_EMPLOYEE) TableExpressionsMustHaveAnAliasForDumbReasons
WHERE rownumber > 0
我觉得所有显示使用 CTE 或子查询的答案都足以解决这个问题,但我没有看到任何人深入了解为什么 OP 有问题。 OP建议不起作用的原因是这里的逻辑查询处理顺序:
- 来自
- 开
- 加入
- 哪里
- 分组依据
- 使用多维数据集/汇总
- 拥有
- 选择
- 独特
- 订购方式
- 顶部
- 偏移/获取
我相信这对答案有很大帮助,因为它解释了为什么会出现这样的问题。
WHERE
始终在 SELECT
进行许多功能所需的 CTE 或子查询之前处理。您会在 SQL Server 中经常看到这种情况。
为了回应对 rexem 答案的评论,关于内联视图或 CTE 是否会更快,我重新设计查询以使用我和每个人都可用的表:sys.objects。
WITH object_rows AS (
SELECT object_id,
ROW_NUMBER() OVER ( ORDER BY object_id) RN
FROM sys.objects)
SELECT object_id
FROM object_rows
WHERE RN > 1
SELECT object_id
FROM (SELECT object_id,
ROW_NUMBER() OVER ( ORDER BY object_id) RN
FROM sys.objects) T
WHERE RN > 1
生成的查询计划完全相同。我希望在所有情况下,查询优化器都会提出相同的计划,至少是用内联视图简单地替换 CTE,反之亦然。
当然,请在自己的系统上尝试自己的查询,看看是否有差异。
此外,where 子句中的
row_number()
是 Stack Overflow 上给出的答案中的常见错误。逻辑上,在处理 select 子句之前,row_number()
不可用。人们忘记了这一点,当他们在没有测试答案的情况下回答时,答案有时是错误的。 (我自己也犯过这个罪名。)
WITH MyCte AS
(
select
employee_id,
RowNum = row_number() OVER (order by employee_id)
from V_EMPLOYEE
)
SELECT employee_id
FROM MyCte
WHERE RowNum > 0
ORDER BY employee_id
使用 CTE(SQL Server 2005+):
WITH employee_rows AS (
SELECT t.employee_id,
ROW_NUMBER() OVER ( ORDER BY t.employee_id ) 'rownum'
FROM V_EMPLOYEE t)
SELECT er.employee_id
FROM employee_rows er
WHERE er.rownum > 1
使用内联视图/非 CTE 等效替代方案:
SELECT er.employee_id
FROM (SELECT t.employee_id,
ROW_NUMBER() OVER ( ORDER BY t.employee_id ) 'rownum'
FROM V_EMPLOYEE t) er
WHERE er.rownum > 1
基于OP对问题的回答:
请查看此链接。它有一个 不同的解决方案,看起来 为提出问题的人工作 问题。我正在尝试找出一个 像这样的解决方案。
在 SQL Server 2005 中使用 ROW_NUMBER() OVER () 对不同列进行排序的分页查询
~约瑟夫
“方法 1”就像来自链接问题的 OP 查询,“方法 2”就像来自所选答案的查询。您必须查看此answer中链接的代码才能了解到底发生了什么,因为所选答案中的代码已被修改以使其正常工作。试试这个:
DECLARE @YourTable table (RowID int not null primary key identity, Value1 int, Value2 int, value3 int)
SET NOCOUNT ON
INSERT INTO @YourTable VALUES (1,1,1)
INSERT INTO @YourTable VALUES (1,1,2)
INSERT INTO @YourTable VALUES (1,1,3)
INSERT INTO @YourTable VALUES (1,2,1)
INSERT INTO @YourTable VALUES (1,2,2)
INSERT INTO @YourTable VALUES (1,2,3)
INSERT INTO @YourTable VALUES (1,3,1)
INSERT INTO @YourTable VALUES (1,3,2)
INSERT INTO @YourTable VALUES (1,3,3)
INSERT INTO @YourTable VALUES (2,1,1)
INSERT INTO @YourTable VALUES (2,1,2)
INSERT INTO @YourTable VALUES (2,1,3)
INSERT INTO @YourTable VALUES (2,2,1)
INSERT INTO @YourTable VALUES (2,2,2)
INSERT INTO @YourTable VALUES (2,2,3)
INSERT INTO @YourTable VALUES (2,3,1)
INSERT INTO @YourTable VALUES (2,3,2)
INSERT INTO @YourTable VALUES (2,3,3)
INSERT INTO @YourTable VALUES (3,1,1)
INSERT INTO @YourTable VALUES (3,1,2)
INSERT INTO @YourTable VALUES (3,1,3)
INSERT INTO @YourTable VALUES (3,2,1)
INSERT INTO @YourTable VALUES (3,2,2)
INSERT INTO @YourTable VALUES (3,2,3)
INSERT INTO @YourTable VALUES (3,3,1)
INSERT INTO @YourTable VALUES (3,3,2)
INSERT INTO @YourTable VALUES (3,3,3)
SET NOCOUNT OFF
DECLARE @PageNumber int
DECLARE @PageSize int
DECLARE @SortBy int
SET @PageNumber=3
SET @PageSize=5
SET @SortBy=1
--SELECT * FROM @YourTable
--Method 1
;WITH PaginatedYourTable AS (
SELECT
RowID,Value1,Value2,Value3
,CASE @SortBy
WHEN 1 THEN ROW_NUMBER() OVER (ORDER BY Value1 ASC)
WHEN 2 THEN ROW_NUMBER() OVER (ORDER BY Value2 ASC)
WHEN 3 THEN ROW_NUMBER() OVER (ORDER BY Value3 ASC)
WHEN -1 THEN ROW_NUMBER() OVER (ORDER BY Value1 DESC)
WHEN -2 THEN ROW_NUMBER() OVER (ORDER BY Value2 DESC)
WHEN -3 THEN ROW_NUMBER() OVER (ORDER BY Value3 DESC)
END AS RowNumber
FROM @YourTable
--WHERE
)
SELECT
RowID,Value1,Value2,Value3,RowNumber
,@PageNumber AS PageNumber, @PageSize AS PageSize, @SortBy AS SortBy
FROM PaginatedYourTable
WHERE RowNumber>=(@PageNumber-1)*@PageSize AND RowNumber<=(@PageNumber*@PageSize)-1
ORDER BY RowNumber
--------------------------------------------
--Method 2
;WITH PaginatedYourTable AS (
SELECT
RowID,Value1,Value2,Value3
,ROW_NUMBER() OVER
(
ORDER BY
CASE @SortBy
WHEN 1 THEN Value1
WHEN 2 THEN Value2
WHEN 3 THEN Value3
END ASC
,CASE @SortBy
WHEN -1 THEN Value1
WHEN -2 THEN Value2
WHEN -3 THEN Value3
END DESC
) RowNumber
FROM @YourTable
--WHERE more conditions here
)
SELECT
RowID,Value1,Value2,Value3,RowNumber
,@PageNumber AS PageNumber, @PageSize AS PageSize, @SortBy AS SortBy
FROM PaginatedYourTable
WHERE
RowNumber>=(@PageNumber-1)*@PageSize AND RowNumber<=(@PageNumber*@PageSize)-1
--AND more conditions here
ORDER BY
CASE @SortBy
WHEN 1 THEN Value1
WHEN 2 THEN Value2
WHEN 3 THEN Value3
END ASC
,CASE @SortBy
WHEN -1 THEN Value1
WHEN -2 THEN Value2
WHEN -3 THEN Value3
END DESC
输出:
RowID Value1 Value2 Value3 RowNumber PageNumber PageSize SortBy
------ ------ ------ ------ ---------- ----------- ----------- -----------
10 2 1 1 10 3 5 1
11 2 1 2 11 3 5 1
12 2 1 3 12 3 5 1
13 2 2 1 13 3 5 1
14 2 2 2 14 3 5 1
(5 row(s) affected
RowID Value1 Value2 Value3 RowNumber PageNumber PageSize SortBy
------ ------ ------ ------ ---------- ----------- ----------- -----------
10 2 1 1 10 3 5 1
11 2 1 2 11 3 5 1
12 2 1 3 12 3 5 1
13 2 2 1 13 3 5 1
14 2 2 2 14 3 5 1
(5 row(s) affected)
select salary from (
select Salary, ROW_NUMBER() over (order by Salary desc) rn from Employee
) t where t.rn = 2