Implementasikan fungsionalitas paging (lewati / ambil) dengan kueri ini

142

Saya telah mencoba untuk memahami sedikit tentang bagaimana menerapkan paging kustom di SQL, misalnya membaca artikel seperti ini .

Saya memiliki pertanyaan berikut, yang berfungsi dengan sempurna. Tapi saya ingin menerapkan paging dengan yang satu ini.

SELECT TOP x PostId FROM ( SELECT PostId, MAX (Datemade) as LastDate
 from dbForumEntry 
 group by PostId ) SubQueryAlias
 order by LastDate desc

Apa yang saya inginkan

Saya memiliki posting forum, dengan entri terkait. Saya ingin mendapatkan postingan dengan entri terbaru yang ditambahkan, jadi saya dapat memilih postingan yang baru-baru ini diperdebatkan.

Sekarang, saya ingin mendapatkan "10 teratas hingga 20 postingan yang baru-baru ini aktif", bukan "10 teratas".

Apa yang sudah saya coba

Saya telah mencoba menerapkan fungsi ROW seperti yang ada di artikel, tetapi benar-benar tidak berhasil.

Ada ide bagaimana menerapkannya?

Lars Holdgaard
sumber

Jawaban:

298

Di SQL Server 2012 ini sangat sangat mudah

SELECT col1, col2, ...
 FROM ...
 WHERE ... 
 ORDER BY -- this is a MUST there must be ORDER BY statement
-- the paging comes here
OFFSET     10 ROWS       -- skip 10 rows
FETCH NEXT 10 ROWS ONLY; -- take 10 rows

Jika kita ingin melewatkan ORDER BY kita bisa menggunakan

SELECT col1, col2, ...
  ...
 ORDER BY CURRENT_TIMESTAMP
OFFSET     10 ROWS       -- skip 10 rows
FETCH NEXT 10 ROWS ONLY; -- take 10 rows

(Saya lebih suka menandainya sebagai retasan - tetapi digunakan, misalnya oleh NHibernate. Untuk menggunakan kolom yang diambil dengan bijak karena ORDER BY lebih disukai)

untuk menjawab pertanyaan:

--SQL SERVER 2012
SELECT PostId FROM 
        ( SELECT PostId, MAX (Datemade) as LastDate
            from dbForumEntry 
            group by PostId 
        ) SubQueryAlias
 order by LastDate desc
OFFSET 10 ROWS -- skip 10 rows
FETCH NEXT 10 ROWS ONLY; -- take 10 rows

Kata kunci baru offsetdan fetch next(hanya mengikuti standar SQL) diperkenalkan.

Tapi saya rasa, Anda tidak menggunakan SQL Server 2012 , bukan ? Pada versi sebelumnya agak (sedikit) sulit. Berikut adalah perbandingan dan contoh untuk semua versi server SQL: di sini

Jadi, ini bisa berfungsi di SQL Server 2008 :

-- SQL SERVER 2008
DECLARE @Start INT
DECLARE @End INT
SELECT @Start = 10,@End = 20;


;WITH PostCTE AS 
 ( SELECT PostId, MAX (Datemade) as LastDate
   ,ROW_NUMBER() OVER (ORDER BY PostId) AS RowNumber
   from dbForumEntry 
   group by PostId 
 )
SELECT PostId, LastDate
FROM PostCTE
WHERE RowNumber > @Start AND RowNumber <= @End
ORDER BY PostId
Radim Köhler
sumber
Terima kasih banyak! Itu jawaban yang sangat bagus! Satu-satunya pertanyaan tentang sql 2008 one. Saya ingin ORDER BY terjadi sebelum WHERE, karena saat ini akan mengurutkan subset, tetapi kami ingin memilih sesuatu dari seluruh rangkaian ... Ada gagasan? :) Sekali lagi, terima kasih
Lars Holdgaard
2
Jika saya benar-benar memahami Anda, Anda ingin mengurutkan berdasarkan LastDate, bukan? maka kita dapat mengubah klausa OVER () dengan cara ini: ROW_NUMBER () OVER (ORDER BY MAX (Datemade) desc ). Dan hapus ORDER BY PostId terakhir . Sekarang CTE harus disortir 'lebih cepat' sesuai kebutuhan. benar?
Radim Köhler
1
Terima kasih ini membantu, catatan tentang sampel 2012, urutan oleh wajib, saya mencoba ini tanpa urutan berdasarkan klausa dan mendapat kesalahan "sintaks salah" tidak tahu apa yang salah sampai saya melihat ke dalam sintaks MSDN dan mengetahui bahwa urutan oleh adalah wajib .
Esen
Apakah baris pertama 1 atau 0? Haruskah DI MANA WHERE RowNumber >= @Start AND RowNumber < @Enduntuk mendapatkan 1000 baris pertama jika @Start0 dan @End1000?
CWSpear
1
Terima kasih banyak
Mafii
8

Untuk melakukan ini di SQL Server, Anda harus mengurutkan kueri menurut kolom, sehingga Anda bisa menentukan baris yang Anda inginkan.

Contoh:

select * from table order by [some_column] 
offset 10 rows
FETCH NEXT 10 rows only

Dan Anda tidak dapat menggunakan kata kunci "TOP" saat melakukan ini.

Anda dapat mempelajari lebih lanjut di sini: https://technet.microsoft.com/pt-br/library/gg699618%28v=sql.110%29.aspx

Felipe VR
sumber
6
OFFSET     10 ROWS       -- skip 10 rows
FETCH NEXT 10 ROWS ONLY; -- take 10 rows

gunakan ini di akhir sintaks pilihan Anda. =)

Nicolas Vinícius Sroczynski
sumber
6

SQL 2008

Jawaban Radim Köhler berhasil, tetapi ini adalah versi yang lebih pendek:

select top 20 * from
(
select *,
ROW_NUMBER() OVER (ORDER BY columnid) AS ROW_NUM
from tablename
) x
where ROW_NUM>10

Sumber: https://forums.asp.net/post/4033909.aspx

Tadej
sumber
0

Perbaikannya adalah dengan memodifikasi file EDMX Anda, menggunakan editor XML, dan mengubah nilai ProviderManifestToken dari 2012 ke 2008 . Saya menemukan itu di baris 7 di file EDMX saya. Setelah menyimpan perubahan itu, paging SQL akan dibuat menggunakan sintaks "lama" yang kompatibel dengan SQL Server 2008.

Saya minta maaf untuk memposting jawaban di utas yang sangat lama ini. Mempostingnya untuk orang-orang seperti saya, saya menyelesaikan masalah ini hari ini.

Syekh M. Haris
sumber
-1

Anda dapat menggunakan kueri bersarang untuk penomoran halaman sebagai berikut:

Paging dari 4 Baris ke 8 Baris di mana ID Pelanggan adalah kunci utama .

SELECT Top 5 * FROM Customers
WHERE Country='Germany' AND CustomerId Not in (SELECT Top 3 CustomerID FROM Customers
WHERE Country='Germany' order by city) 
order by city;
amoljdv06.dll
sumber