Saya menemukan satu pertanyaan terjawab dengan Row_Number()
fungsi di klausa where. Ketika saya mencoba satu kueri, saya mendapatkan kesalahan berikut:
"Msg 4108, Level 15, State 1, Line 1 Windowed functions hanya dapat muncul di klausa SELECT atau ORDER BY."
Inilah pertanyaan yang saya coba. Jika ada yang tahu cara menyelesaikan ini, beri tahu saya.
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
johnnyRose
sumber
sumber
ROW_NUMBER() OVER (ORDER BY employee_id) > 0
akan selalu mengevaluasi keTRUE
Jawaban:
Untuk mengatasi masalah ini, bungkus pernyataan pemilihan Anda dalam CTE, dan kemudian Anda dapat melakukan kueri terhadap CTE dan menggunakan hasil fungsi berjendela di klausa 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
sumber
ROW_NUMBER()
diWHERE
klausul tanpa CTE :(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
Perhatikan bahwa filter ini berlebihan:
ROW_NUMBER()
dimulai dari1
dan selalu lebih besar dari0
.sumber
AS q
sebagai gantinya, tetapi ini juga akan berhasil).rn
adalah akronim yang diterima secara universal untuk nomor baris saat ini. Coba ketikkan "row_number over as ..." ke dalam string pencarian google dan lihat apa yang disarankannya untuk Anda.Select * from ( Select ROW_NUMBER() OVER ( order by Id) as 'Row_Number', * from tbl_Contact_Us ) as tbl Where tbl.Row_Number = 5
sumber
Saya pikir Anda menginginkan sesuatu seperti ini:
SELECT employee_id FROM (SELECT employee_id, row_number() OVER (order by employee_id) AS 'rownumber' FROM V_EMPLOYEE) TableExpressionsMustHaveAnAliasForDumbReasons WHERE rownumber > 0
sumber
From V_EMPLOYEE) A
menambahkan A sebagai alias.Menanggapi komentar pada jawaban rexem, sehubungan dengan apakah tampilan inline atau CTE akan lebih cepat, saya menyusun ulang kueri untuk menggunakan tabel I, dan semua orang, telah tersedia: 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
Rencana kueri yang dihasilkan persis sama. Saya berharap dalam semua kasus, pengoptimal kueri akan menghasilkan rencana yang sama, setidaknya dalam penggantian sederhana CTE dengan tampilan sebaris atau sebaliknya.
Tentu saja, coba kueri Anda sendiri di sistem Anda sendiri untuk melihat apakah ada perbedaan.
Juga,
row_number()
di mana klausa adalah kesalahan umum dalam jawaban yang diberikan di Stack Overflow. Logicalyrow_number()
tidak tersedia sampai klausa pemilihan diproses. Orang-orang melupakannya dan ketika mereka menjawab tanpa menguji jawabannya, terkadang jawabannya salah. (Tuduhan yang membuat saya sendiri bersalah.)sumber
Saya merasa semua jawaban yang menunjukkan penggunaan CTE atau Sub Query adalah perbaikan yang cukup untuk ini, tetapi saya tidak melihat ada yang sampai pada inti mengapa OP memiliki masalah. Alasan mengapa apa yang disarankan OP tidak berfungsi adalah karena urutan pemrosesan kueri logis di sini:
Saya yakin ini berkontribusi besar pada jawaban, karena menjelaskan mengapa masalah seperti ini terjadi.
WHERE
selalu diproses sebelumSELECT
membuat CTE atau Sub Query yang diperlukan untuk banyak fungsi. Anda akan sering melihat ini di SQL Server.sumber
Menggunakan 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
Menggunakan Tampilan Inline / Alternatif Setara 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
sumber
SQL Server
,CTE
tampilan dan inline adalah hal yang sama dan memiliki kinerja yang sama. Ketika fungsi non-deterministik digunakan dalam aCTE
, fungsi tersebut dievaluasi ulang pada setiap panggilan. Seseorang harus menggunakan trik kotor untuk memaksa perwujudan aCTE
. Lihat artikel ini di blog saya: menjelaskanextended.com/2009/07/28/… menjelaskanextended.com/2009/05/28/generating-xml-in-subqueriesberdasarkan jawaban OP atas pertanyaan:
"metode 1" seperti kueri OP dari pertanyaan terkait, dan "metode 2" seperti kueri dari jawaban yang dipilih. Anda harus melihat kode yang ditautkan dalam jawaban ini untuk mengetahui apa yang sebenarnya terjadi, karena kode dalam jawaban yang dipilih telah dimodifikasi untuk membuatnya berfungsi. Coba ini:
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
KELUARAN:
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)
sumber
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
sumber
select salary from ( select Salary, ROW_NUMBER() over (order by Salary desc) rn from Employee ) t where t.rn = 2
sumber