Функция SQL Row_Number() в разделе Where Where
Я нашел один вопрос, отвечающий с помощью функции Row_Number()
в предложении where. Когда я попробовал один запрос, я получил следующую ошибку:
"Msg 4108, уровень 15, состояние 1, строка 1 Оконные функции могут отображаться только в предложениях SELECT или ORDER BY."
Вот запрос, который я попробовал. Если кто-то знает, как это решить, сообщите мне.
SELECT employee_id
FROM V_EMPLOYEE
WHERE row_number() OVER ( ORDER BY employee_id ) > 0
ORDER BY Employee_ID
Ответы
Ответ 1
Чтобы обойти эту проблему, оберните оператор 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
Ответ 2
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
.
Ответ 3
Select * from
(
Select ROW_NUMBER() OVER ( order by Id) as 'Row_Number', *
from tbl_Contact_Us
) as tbl
Where tbl.Row_Number = 5
Ответ 4
Я думаю, вам нужно что-то вроде этого:
SELECT employee_id
FROM (SELECT employee_id, row_number()
OVER (order by employee_id) AS 'rownumber'
FROM V_EMPLOYEE) TableExpressionsMustHaveAnAliasForDumbReasons
WHERE rownumber > 0
Ответ 5
В ответ на комментарии к ответу rexem, относительно того, будет ли развернутый просмотр или CTE быстрее, я перепрограммирую запросы на использование таблицы I, и у всех есть: 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 встроенным представлением или наоборот.
Конечно, попробуйте свои собственные запросы в своей собственной системе, чтобы увидеть, есть ли разница.
Кроме того, row_number()
в предложении where является общей ошибкой в ответах, приведенных в разделе Переполнение стека. Логически row_number()
недоступен до тех пор, пока не будет обработано предложение select. Люди забывают об этом, и когда они отвечают без проверки ответа, ответ иногда ошибочен. (Обвинение, в котором я сам виноват.)
Ответ 6
Использование 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
Использование Inline view/Non-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
Ответ 7
на основе ответа OP на вопрос:
Пожалуйста, просмотрите эту ссылку. Имея другое решение, которое выглядит работая для человека, который спросил вопрос. Я пытаюсь выяснить решение, подобное этому.
Разбитый запрос с использованием сортировки по разным столбцам с использованием ROW_NUMBER() OVER() в SQL Server 2005
~ Джозеф
"метод 1" подобен запросу OP из связанного вопроса, а "метод 2" похож на запрос из выбранного ответа. Вам нужно было посмотреть код, связанный в этом , чтобы узнать, что действительно происходит, поскольку код в выбранном ответе был изменен, чтобы заставить его работать. Попробуйте следующее:
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)
Ответ 8
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
Ответ 9
Я чувствую, что все ответы, показывающие использование CTE или подзапроса, являются достаточными исправлениями для этого, но я не вижу, чтобы кто-то понимал, почему у OP есть проблема. Причина, по которой предложенный OP не работает, заключается в том, что логический порядок обработки запросов здесь:
-
ОТ
- ON
- РЕГИСТРИРУЙТЕСЬ
- ГДЕ
- GROUP BY
- С КУБОМ /ROLLUP
- HAVING
- ВЫБРАТЬ
- DISTINCT
- ЗАКАЗАТЬ
- TOP
- OFFSET/FETCH
Я считаю, что это очень помогает в ответе, потому что объясняет, почему возникают подобные проблемы. WHERE
всегда обрабатывается перед тем, как SELECT
делает CTE или подзапрос, необходимый для многих функций. Вы многое увидите в SQL Server.
Ответ 10
если необходимо добавить условие динамически, вы можете использовать в запросе:
SELECT f0.*
FROM FOO f0
WHERE EXISTS
(SELECT f2.foo_id
FROM
(SELECT foo_id ,
ROW_NUMBER() OVER( PARTITION BY F1.BAR_ID ORDER BY F1.AMOUNT) rk
FROM foo f1
)f2
WHERE f0.foo_id=f2.foo_id
AND rk =2 -- your condition on row_number goes here
);
Ответ 11
select salary from (
select Salary, ROW_NUMBER() over (order by Salary desc) rn from Employee
) t where t.rn = 2