Bagaimana cara mengimplementasikan LIMIT dengan SQL Server?

Jawaban:

127

Mulai SQL SERVER 2005, Anda dapat melakukan ini ...

USE AdventureWorks;
GO
WITH OrderedOrders AS
(
    SELECT SalesOrderID, OrderDate,
    ROW_NUMBER() OVER (ORDER BY OrderDate) AS 'RowNumber'
    FROM Sales.SalesOrderHeader 
) 
SELECT * 
FROM OrderedOrders 
WHERE RowNumber BETWEEN 10 AND 20;

atau sesuatu seperti ini untuk versi 2000 dan di bawah ...

SELECT TOP 10 * FROM (SELECT TOP 20 FROM Table ORDER BY Id) ORDER BY Id DESC
Leon Tayson
sumber
6
Kueri ke-2 gagal jika Anda memiliki mis. 14 baris dalam tabel. Ini memberi Anda baris 5 hingga 14, tetapi Anda ingin baris 11 hingga 14. Secara umum, ia gagal untuk "halaman" hasil terakhir, kecuali jika total baris adalah kelipatan dari ukuran "halaman" itu.
Bill Karwin
147
Hal sederhana seperti itu perlu dipersulit lagi oleh MS!
Martin
Inilah yang bekerja untuk saya di SQL Server Management Studio 2017: SELECT * FROM [dbo]. <Insert tableName here> WHERE @@ ROWCOUNT ANTARA <masukkan min di sini> dan <masukkan max di sini>
Artorias2718
Hanya Fantastis, Ini berfungsi seperti pesona di MS SQL Server 2017 pilih Pernyataan
PatsonLeaner
58

Kikuk, tapi itu akan berhasil.

SELECT TOP 10 * FROM table WHERE id NOT IN (SELECT TOP 10 id FROM table ORDER BY id) FROM table ORDER BY id

Penghapusan klausa LIMIT MSSQL adalah kriminal, IMO. Anda tidak harus melakukan penyelesaian seperti ini.

ceejayoz
sumber
Apakah Anda punya saran lain untuk melewati ini?
Bigballs
Saya melakukan banyak Googling terakhir kali saya harus berurusan dengan MSSQL dan ini adalah solusi terbaik yang saya temukan. Tidak menyenangkan, tetapi berhasil.
ceejayoz
Solusi ini hanya berfungsi jika set hasil menyertakan kolom yang unik. Ini bukan solusi umum untuk meniru LIMIT untuk kueri apa pun.
Bill Karwin
1
Saya dalam kesulitan yang sama sekarang ... Namun, dalam kasus saya, saya disembunyikan ... Itu bahkan lebih kriminal ketika disebut 'pakar' dba memutuskan bahwa kunci unik tidak diperlukan dalam sebuah tabel ... Tabel APAPUN ... Jangan bahas masalah kunci dan batasan asing!
Andrew Rollings
Masalah dengan ini adalah, itu tidak menangani klausa WHERE dengan sangat baik ... Saya akan mencoba tabel temp, karena tidak bekerja untuk saya.
Nasty pasty
37

Dimulai dengan SQL SERVER 2012, Anda dapat menggunakan OFFSET FETCH Clause:

USE AdventureWorks;
GO
SELECT SalesOrderID, OrderDate
FROM Sales.SalesOrderHeader 
ORDER BY SalesOrderID
    OFFSET 10 ROWS
    FETCH NEXT 10 ROWS ONLY;
GO

http://msdn.microsoft.com/en-us/library/ms188385(v=sql.110).aspx

Ini mungkin tidak berfungsi dengan benar ketika pesanan oleh tidak unik.

Jika kueri diubah menjadi ORDER BY OrderDate, hasil yang dikembalikan tidak seperti yang diharapkan.

pengguna4047259
sumber
Menggunakan 'dengan' hanya perlu separuh waktu untuk menyelesaikan pertanyaan - lihat jawaban @Leon Tayson. Saya tidak tahu apa yang dilakukan Microsoft untuk membuatnya menjadi sangat lambat.
isHuman
1
Mengapa ini bukan jawaban yang diterima? Kami berada di 2018 untuk menangis dengan suara keras!
Kapten
1
@Skipper benar. yang diterima masih berfungsi. Mari kita pilih yang ini untuk mencerminkan pembaruan.
kronn
18

Ini hampir merupakan duplikat dari pertanyaan yang saya ajukan pada bulan Oktober: Meniru klausa LIMIT MySQL di Microsoft SQL Server 2000

Jika Anda menggunakan Microsoft SQL Server 2000, tidak ada solusi yang baik. Sebagian besar orang harus menggunakan untuk menangkap hasil kueri dalam tabel sementara dengan IDENTITYkunci utama. Kemudian kueri terhadap kolom kunci utama menggunakan BETWEENkondisi.

Jika Anda menggunakan Microsoft SQL Server 2005 atau lebih baru, Anda memiliki ROW_NUMBER()fungsi, sehingga Anda bisa mendapatkan hasil yang sama tetapi menghindari tabel sementara.

SELECT t1.*
FROM (
    SELECT ROW_NUMBER OVER(ORDER BY id) AS row, t1.*
    FROM ( ...original SQL query... ) t1
) t2
WHERE t2.row BETWEEN @offset+1 AND @offset+@count;

Anda juga dapat menulis ini sebagai ekspresi tabel umum seperti yang ditunjukkan pada jawaban @Leon Tayson .

Bill Karwin
sumber
ROW_NUMBER () OVER (ORDER BY) mendapatkan poin untuk valid dalam ANSI SQL: 2003, meskipun dukungan dalam DBMS selain SQL Server sangat buruk. Dan itu cukup kikuk tentu saja ...
bobince
@obobince: Ternyata Oracle, Microsoft SQL Server 2005, IBM DB2, dan PostgreSQL 8.4 semua fungsi jendela dukungan. Itu mencakup sebagian besar pasar SQL. Dukungan hanya jerawatan jika Anda menggunakan MySQL, SQLite atau versi lama DB di atas.
Bill Karwin
16

Ini adalah bagaimana saya membatasi hasil dalam MS SQL Server 2012:

SELECT * 
FROM table1
ORDER BY columnName
  OFFSET 10 ROWS FETCH NEXT 10 ROWS ONLY

CATATAN: OFFSEThanya dapat digunakan dengan atau bersama-sama dengan ORDER BY.

Untuk menjelaskan baris kode OFFSET xx ROWS FETCH NEXT yy ROW ONLY

Ini xxadalah nomor record / baris yang ingin Anda tarik dari dalam tabel, yaitu: Jika ada 40 catatan dalam tabel 1, kode di atas akan mulai menarik dari baris 10.

The yyadalah jumlah record / baris Anda ingin menarik dari meja.

Untuk membangun contoh sebelumnya: Jika tabel 1 memiliki 40 catatan dan Anda mulai menarik dari baris 10 dan ambil set NEXT dari 10 ( yy). Itu berarti, kode di atas akan menarik catatan dari tabel 1 mulai dari baris 10 dan berakhir pada 20. Dengan demikian menarik baris 10 - 20.

Lihat tautan untuk info lebih lanjut tentang OFFSET

Jeremy
sumber
12
SELECT  *
FROM    (
        SELECT  TOP 20
                t.*, ROW_NUMBER() OVER (ORDER BY field1) AS rn
        FROM    table1 t
        ORDER BY
                field1
        ) t
WHERE   rn > 10
Quassnoi
sumber
Yah, saya baru saja memeriksa, SQL Server ternyata cukup pintar untuk berhenti pada kondisi ROW_NUMBER (), jika ada kolom yang diindeks dalam klausa ORDER BY.
Quassnoi
9

Permintaan MySQL LIMIT secara sintaksis adalah seperti ini:

SELECT * FROM table LIMIT OFFSET, ROW_COUNT

Ini dapat diterjemahkan ke dalam Microsoft SQL Server seperti

SELECT * FROM 
(
    SELECT TOP #{OFFSET+ROW_COUNT} *, ROW_NUMBER() OVER (ORDER BY (SELECT 1)) AS rnum 
    FROM table
) a
WHERE rnum > OFFSET

Sekarang permintaan Anda select * from table1 LIMIT 10,20akan seperti ini:

SELECT * FROM 
(
    SELECT TOP 30 *, ROW_NUMBER() OVER (ORDER BY (SELECT 1)) AS rnum 
    FROM table1
) a
WHERE rnum > 10 

sumber
2

Ini adalah salah satu alasan saya mencoba untuk menghindari menggunakan MS Server ... tetapi tetap. Kadang-kadang Anda tidak memiliki opsi (yei! Dan saya harus menggunakan versi yang sudah usang !!).

Saran saya adalah membuat tabel virtual:

Dari:

SELECT * FROM table

Untuk:

CREATE VIEW v_table AS    
    SELECT ROW_NUMBER() OVER (ORDER BY table_key) AS row,* FROM table

Maka cukup kueri:

SELECT * FROM v_table WHERE row BETWEEN 10 AND 20

Jika bidang ditambahkan, atau dihapus, "baris" diperbarui secara otomatis.

Masalah utama dengan opsi ini adalah bahwa ORDER BY sudah diperbaiki. Jadi jika Anda menginginkan urutan yang berbeda, Anda harus membuat tampilan lain.

MEMPERBARUI

Ada masalah lain dengan pendekatan ini: jika Anda mencoba memfilter data Anda, itu tidak akan berfungsi seperti yang diharapkan. Misalnya, jika Anda melakukannya:

SELECT * FROM v_table WHERE field = 'test' AND row BETWEEN 10 AND 20

DI MANA menjadi terbatas pada data yang berada di baris antara 10 dan 20 (alih-alih mencari seluruh dataset dan membatasi output).

lepe
sumber
1

Ini adalah pendekatan multi langkah yang akan bekerja di SQL2000.

-- Create a temp table to hold the data
CREATE TABLE #foo(rowID int identity(1, 1), myOtherColumns)

INSERT INTO #foo (myColumns) SELECT myData order By MyCriteria

Select * FROM #foo where rowID > 10
souLTower
sumber
1
SELECT 
    * 
FROM 
    (
        SELECT 
            top 20              -- ($a) number of records to show
            * 
        FROM
            (
                SELECT 
                    top 29      -- ($b) last record position
                    * 
                FROM 
                    table       -- replace this for table name (i.e. "Customer")
                ORDER BY 
                    2 ASC
            ) AS tbl1 
        ORDER BY 
            2 DESC
    ) AS tbl2 
ORDER BY 
    2 ASC;

-- Examples:

-- Show 5 records from position 5:
-- $a = 5;
-- $b = (5 + 5) - 1
-- $b = 9;

-- Show 10 records from position 4:
-- $a = 10;
-- $b = (10 + 4) - 1
-- $b = 13;

-- To calculate $b:
-- $b = ($a + position) - 1

-- For the present exercise we need to:
-- Show 20 records from position 10:
-- $a = 20;
-- $b = (20 + 10) - 1
-- $b = 29;
Julian Moreno
sumber
Merupakan solusi yang bagus untuk saya.
Tyde
1

Harus dicoba. Di kueri di bawah ini, Anda bisa melihat grup berdasarkan, pesan berdasar, Lewati baris, dan bataskan baris.

select emp_no , sum(salary_amount) from emp_salary
Group by emp_no 
ORDER BY emp_no 
OFFSET 5 ROWS       -- Skip first 5 
FETCH NEXT 10 ROWS ONLY; -- limit to retrieve next 10 row after skiping rows
M Denmark
sumber
0
SELECT TOP 10 * FROM table;

Sama dengan

SELECT * FROM table LIMIT 0,10;

Inilah artikel tentang menerapkan Batas dalam MSSQL. Ini adalah bacaan yang bagus, khususnya komentar.

Ólafur Waage
sumber
1
Terima kasih, tapi saya ingin rekaman antara 10 dan 20, ada cara untuk melakukannya?
Bigballs
5
Jawaban ini tidak menanggapi pertanyaan asal, tetapi itu berguna jika seseorang seperti saya perlu tahu bagaimana mendapatkan hasil N pertama dan sampai di sini melalui google dll ...
brianlmerritt
0

Di SQL tidak ada kata kunci LIMIT. Jika Anda hanya membutuhkan jumlah baris terbatas, Anda harus menggunakan kata kunci TOP yang mirip dengan LIMIT.

Mitul Panchal
sumber
0

Jika ID Anda adalah tipe pengidentifikasi unik atau id dalam tabel Anda tidak diurutkan, Anda harus melakukan seperti ini di bawah ini.

select * from
(select ROW_NUMBER() OVER (ORDER BY (select 0)) AS RowNumber,* from table1) a
where a.RowNumber between 2 and 5



Kodenya akan

pilih * dari batas 2,5
pengguna3244012
sumber
0

lebih baik gunakan ini di MSSQLExpress 2017.

SELECT * FROM
(
    SELECT ROW_NUMBER() OVER (ORDER BY (SELECT 0)) as [Count], * FROM table1
) as a
WHERE [Count] BETWEEN 10 and 20;

--Memberikan Kolom [Hitungan] dan menugaskan setiap baris penghitungan unik tanpa memesan sesuatu lalu pilih kembali di mana Anda dapat memberikan batasan Anda .. :)

pengguna1308314
sumber
0

Salah satu cara yang mungkin untuk mendapatkan hasil seperti di bawah ini, harap ini akan membantu.

declare @start int
declare @end int
SET @start = '5000';  -- 0 , 5000 ,
SET @end = '10000'; -- 5001, 10001
SELECT * FROM ( 
  SELECT TABLE_NAME,TABLE_TYPE, ROW_NUMBER() OVER (ORDER BY TABLE_NAME) as row FROM information_schema.tables
 ) a WHERE a.row > @start and a.row <= @end
Pragnesh Karia
sumber
0

Jalan mudah

MYSQL:

SELECT 'filds' FROM 'table' WHERE 'where' LIMIT 'offset','per_page'

MSSQL:

SELECT 'filds' FROM 'table' WHERE 'where' ORDER BY 'any' OFFSET 'offset' 
ROWS FETCH NEXT 'per_page' ROWS ONLY

ORDER BY wajib diisi

Turendu
sumber
-2

Jika saya ingat dengan benar (sudah lama sejak saya mengoleskan SQL Server), Anda mungkin dapat menggunakan sesuatu seperti ini: (2005 dan lebih tinggi)

SELECT
    *
   ,ROW_NUMBER() OVER(ORDER BY SomeFields) AS [RowNum]
FROM SomeTable
WHERE RowNum BETWEEN 10 AND 20
Keris
sumber
SQL Server 2012: Msg 207, Level 16, Negara 1, Baris 5 Nama kolom tidak valid 'RowNum'.
e-info128
Sepertinya Anda salah ketik dalam pernyataan Anda di suatu tempat. RowNum adalah nama yang kami berikan untuk ekspresi. Poskan masalah Anda dengan sumber dan komunitas akan membantu Anda
Kris
Ini bukan sintaks yang valid. Anda tidak dapat merujuk pada WHEREalias yang ditentukan dalam SELECTklausa level yang sama .
ypercubeᵀᴹ