Я нашел один вопрос, на который отвечает 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
sql
sql-server
tsql
analytic-functions
Джонни Роуз
источник
источник
ROW_NUMBER() OVER (ORDER BY employee_id) > 0
всегда буду оцениватьTRUE
Ответы:
Чтобы обойти эту проблему, оберните оператор 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
источник
ROW_NUMBER()
вWHERE
предложении без КТРА :(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
.источник
AS q
вместо него, но это тоже сработает).rn
является общепринятым аббревиатурой для номера строки. Попробуйте ввести "row_number over as ..." в строку поиска Google и посмотрите, что вам предложат.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
источник
From V_EMPLOYEE) A
, добавив в качестве псевдонима A.В ответ на комментарии к ответу 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 на встроенное представление или наоборот.
Конечно, попробуйте свои собственные запросы в своей системе, чтобы увидеть, есть ли разница.
Кроме того,
row_number()
в предложении where встречается распространенная ошибка в ответах на Stack Overflow. Логикаrow_number()
недоступна, пока не будет обработано предложение select. Люди забывают об этом, и когда они отвечают, не проверив ответ, иногда ответ оказывается неверным. (Обвинение, в котором я сам был виновен.)источник
Мне кажется, что все ответы, показывающие использование CTE или Sub Query, являются достаточными исправлениями для этого, но я не вижу, чтобы кто-то понял, почему у OP проблема. Причина, по которой предложенный OP не работает, связана с логическим порядком обработки запросов здесь:
Я считаю, что это в значительной степени способствует ответу, поскольку объясняет, почему возникают подобные проблемы.
WHERE
всегда обрабатывается доSELECT
создания CTE или подзапроса, необходимого для многих функций. Вы часто будете видеть это в SQL Server.источник
Использование 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
источник
SQL Server
,CTE
и встроенные представления - это одно и то же и имеют одинаковую производительность. Когда в a используются недетерминированные функции, ониCTE
переоцениваются при каждом вызове. Чтобы принудительно материализовать файл, нужно использовать грязные уловкиCTE
. Смотрите эти статьи в моем блоге: explainextended.com/2009/07/28/... explainextended.com/2009/05/28/generating-xml-in-subqueriesна основе ответа OP на вопрос:
«метод 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)
источник
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
источник
select salary from ( select Salary, ROW_NUMBER() over (order by Salary desc) rn from Employee ) t where t.rn = 2
источник