SQL Server PILIH Baris N TERAKHIR

147

Ini adalah pertanyaan yang diketahui tetapi solusi terbaik yang saya temukan adalah seperti:

SELECT TOP N *
FROM MyTable
ORDER BY Id DESC

Saya punya meja dengan banyak baris. Ini bukan kemungkinan untuk menggunakan kueri itu karena itu membutuhkan banyak waktu. Jadi bagaimana saya bisa memilih N baris terakhir tanpa menggunakan ORDER BY?

EDIT

Maaf pertanyaan digandakan yang satu ini

Diego
sumber
Apa yang dimaksud dengan "N terakhir"? Tanpa urutan, "N terakhir" tidak masuk akal. Jika yang Anda maksud adalah "N terakhir untuk disisipkan" maka Anda tidak dapat mengandalkan SQL Server untuk memberikannya kepada Anda - Anda harus menggunakan klausa ORDER BY.
Daniel Renshaw
@Daniel Renshaw: N terakhir dari tabel tanpa memaksa SQL Server untuk memesan semua tabel karena menjadi sangat lambat
Diego
Kueri dalam pertanyaan Anda adalah cara terbaik. Jika iddiindeks maka itu hanya akan memindai indeks itu secara terbalik dan berhenti setelah 5 baris pertama. Jika tidak diindeks maka perlu dilakukan TOP Npenyortiran. Ini tidak akan lebih buruk daripada cara lain untuk melakukannya. Itu tidak menyortir seluruh tabel (meskipun itu perlu memindai seluruh tabel)
Martin Smith

Jawaban:

39

Anda juga dapat melakukannya dengan menggunakan Fitur ROW NUMBER BY PARTITION. Contoh yang bagus dapat ditemukan di sini :

Saya menggunakan tabel Pesanan dari database Northwind ... Sekarang mari kita ambil 5 pesanan terakhir yang dilakukan oleh Karyawan 5:

SELECT ORDERID, CUSTOMERID, OrderDate
FROM
(
    SELECT ROW_NUMBER() OVER (PARTITION BY EmployeeID ORDER BY OrderDate DESC) AS OrderedDate,*
    FROM Orders
) as ordlist

WHERE ordlist.EmployeeID = 5
AND ordlist.OrderedDate <= 5
JonVD
sumber
1
Fitur NOMOR BARIS BERDASARKAN PARTISI menggunakan semacam juga .. Anda perlu mengurutkan tabel untuk menetapkan nomor baris untuk setiap record ...
Sadhir
Ini benar, tetapi tanpa semacam sifat ini tidak akan berfungsi, solusi terbaik adalah mengindeks kolom utama yang dipukul dan dijalankan dengan sesuatu seperti kueri di atas.
JonVD
109

Anda dapat membuat SQL server untuk memilih baris N terakhir menggunakan SQL ini:

select * from tbl_name order by id desc limit N;
Niru Mukund Shah
sumber
2
Bagaimana dengan kompatibilitas versi?
Fractaliste
67
Ini tidak berfungsi di SQL Server. Sepertinya fitur MySQL, PostgreSQL, dan SQLite.
Tim Friesen
3
Semua produk yang disebutkan pasti adalah server SQL. Jika Anda ingin berbicara tentang server MS SQL, mengapa tidak dinamai demikian?
gena2x
4
saya bingung, pertanyaannya menanyakan cara membuat kueri pemilihan "tanpa menggunakan ORDER BY" dan kueri pemilihan dalam jawaban Anda memiliki "pesan menurut". Apakah ini semacam "dipesan oleh" tanpa "dipesan oleh"?
Robert Sinclair
5
@ gena2x pertanyaan ini diberi tag SQL Server. Tag tersebut merujuk ke Microsoft SQL Server.
Martin Smith
55

Saya menguji kode JonVD, tetapi ternyata sangat lambat, 6s.

Kode ini membutuhkan 0 detik.

SELECT TOP(5) ORDERID, CUSTOMERID, OrderDate    
FROM Orders where EmployeeID=5    
Order By OrderDate DESC
ABI
sumber
4
Berapa baris ?? Bila Anda memiliki banyak baris yang bisa BENAR-BENAR lambat
Diego
@Diego Mengapa demikian? Jika Anda telah OrderDatediindeks, itu pada dasarnya harus sama cepatnya untuk memilih baris N pertama atau terakhir dari sebuah kueri. Saya menyadari ada kemungkinan OrderDateberkorelasi dengan baik untuk pesanan yang dimasukkan, tapi itu efek samping yang terbaik, dan masih memerlukan pemindaian tabel, bukan? (Dan saya tidak berpikir itu menjawab apa yang OP menunjuk sebagai
penipu frase yang
1
@Diego - Mengapa Anda yakin bahwa ini akan lebih lambat dari jawaban yang Anda terima?
Martin Smith
3
Ini mengembalikan baris secara terbalik. Anda kemudian harus memesan ulang oleh mereka untuk mendapatkan kembali pesanan aslinya.
Tandai
15

Jika Anda ingin memilih jumlah baris terakhir dari tabel.

Sintaksnya akan seperti

 select * from table_name except select top 
 (numbers of rows - how many rows you want)* from table_name

Pernyataan ini bekerja tetapi dengan cara yang berbeda. Terima kasih kawan.

 select * from Products except select top (77-10) * from Products

dengan cara ini Anda bisa mendapatkan 10 baris terakhir tetapi urutan akan menunjukkan cara yang jelas

select top 10 * from products
 order by productId desc 

 select * from products
 where productid in (select top 10 productID from products)
 order by productID desc

 select * from products where productID not in 
 (select top((select COUNT(*) from products ) -10 )productID from products)
Prafulla Sutradhar
sumber
7

Dengan cara yang sangat umum dan untuk mendukung SQL server di sini adalah

SELECT TOP(N) *
FROM tbl_name
ORDER BY tbl_id DESC

dan untuk kinerjanya, tidak buruk (kurang dari satu detik untuk lebih dari 10.000 catatan di mesin Server)

Hakan Fıstık
sumber
2
baik 10'000 catatan tidak ada yang harus Anda pikirkan tentang kinerja. Saat Anda mulai berbicara tentang jutaan rekaman daripada yang dapat Anda pikirkan tentang kinerja
Dom84
6

Apakah "Id" diindeks? Jika tidak, itu penting untuk dilakukan (saya curiga sudah diindeks).

Juga, apakah Anda perlu mengembalikan SEMUA kolom? Anda mungkin bisa mendapatkan peningkatan kecepatan yang substansial jika Anda hanya benar-benar membutuhkan subset kolom yang lebih kecil yang dapat SEPENUHNYA dipenuhi oleh indeks pada kolom ID - misalnya jika Anda memiliki indeks NONCLUSTERED pada kolom Id, tanpa yang lain bidang yang disertakan dalam indeks, maka itu harus melakukan pencarian pada indeks berkerumun untuk benar-benar mendapatkan sisa kolom untuk dikembalikan dan itu bisa membuat banyak biaya kueri. Jika itu adalah indeks TERKELUP, atau indeks NONCLUSTERED yang menyertakan semua bidang lain yang ingin Anda kembalikan dalam kueri, Anda akan baik-baik saja.

AdaTheDev
sumber
6

Pertama, Anda paling banyak mendapatkan jumlah rekor

 Declare @TableRowsCount Int
 select @TableRowsCount= COUNT(*) from <Your_Table>

Lalu :

Di SQL Server 2012

SELECT *
FROM  <Your_Table> As L
ORDER BY L.<your Field>
OFFSET <@TableRowsCount-@N> ROWS
FETCH NEXT @N ROWS ONLY;

Di SQL Server 2008

SELECT *
FROM 
(
SELECT ROW_NUMBER() OVER(ORDER BY ID) AS sequencenumber, *
FROM  <Your_Table>
    Order By <your Field>
) AS TempTable
WHERE sequencenumber > @TableRowsCount-@N 
Ardalan Shahgholi
sumber
4

Inilah sesuatu yang dapat Anda coba tanpa order bytetapi saya pikir itu mengharuskan setiap baris unik. Nadalah jumlah baris yang Anda inginkan, Ladalah jumlah baris dalam tabel.

select * from tbl_name except select top L-N * from tbl_name

Seperti disebutkan sebelumnya, baris mana yang dikembalikan tidak ditentukan.

EDIT: ini sebenarnya anjing lambat. Tidak ada nilainya.

Dzamo Norton
sumber
4
select * from (select top 6 * from vwTable order by Hours desc) T order by Hours
fth
sumber
2

Kueri ini mengembalikan baris N terakhir dalam urutan yang benar, tetapi kinerjanya buruk

select *
from (
    select top N *
    from TableName t
    order by t.[Id] desc
) as temp
order by temp.[Id]
timberhill
sumber
2

gunakan desc dengan orderby di akhir kueri untuk mendapatkan nilai terakhir.

Sara
sumber
2

MS tidak mendukung LIMIT di t-sql. Seringkali saya hanya mendapatkan MAX (ID) dan kemudian mengurangi.

select * from ORDERS where ID >(select MAX(ID)-10 from ORDERS)

Ini akan mengembalikan kurang dari 10 catatan jika ID tidak berurutan.

olafk.dll
sumber
1

Ini mungkin tidak sesuai dengan pertanyaan, tapi…

Klausa OFFSET

The OFFSET numberklausul memungkinkan Anda untuk melewatkan lebih dari satu nomor baris dan kemudian kembali baris setelah itu.

Tautan dokumen itu ke Postgres; Saya tidak tahu apakah ini berlaku untuk Sybase / MS SQL Server.

Basil Bourque
sumber
1
DECLARE @MYVAR  NVARCHAR(100)
DECLARE @step  int
SET @step = 0;


DECLARE MYTESTCURSOR CURSOR
DYNAMIC 
FOR
SELECT col FROM [dbo].[table]
OPEN MYTESTCURSOR
FETCH LAST FROM MYTESTCURSOR INTO @MYVAR
print @MYVAR;


WHILE @step < 10
BEGIN   
    FETCH PRIOR FROM MYTESTCURSOR INTO @MYVAR
        print @MYVAR;
        SET @step = @step + 1;
END   
CLOSE MYTESTCURSOR
DEALLOCATE MYTESTCURSOR
Slava
sumber
0

Sebuah teknik yang saya gunakan untuk menanyakan baris TERBARU dalam tabel yang sangat besar (100+ juta atau 1+ miliar baris) membatasi kueri untuk "membaca" hanya persentase "N" terbaru dari BARIS TERBARU. Ini adalah aplikasi dunia nyata, misalnya saya melakukan ini untuk Data Cuaca Terkini non-historis, atau pencarian umpan Berita terkini atau data titik data lokasi GPS terkini.

Ini adalah peningkatan kinerja yang sangat besar jika Anda mengetahui dengan pasti bahwa baris Anda berada di TOP 5% tabel terbaru misalnya. Bahkan jika ada indeks pada Tabel, lebih jauh membatasi kemungkinan hanya 5% dari baris dalam tabel yang memiliki 100+ juta atau 1+ miliar baris. Hal ini terutama terjadi ketika Data Lama akan membutuhkan pembacaan Disk Fisik dan tidak hanya Logical In Memory Pembacaan .

Ini jauh lebih efisien daripada SELECT TOP | PERCENT | LIMIT karena tidak memilih baris, tetapi hanya membatasi porsi data yang akan dicari.

DECLARE @RowIdTableA BIGINT
DECLARE @RowIdTableB BIGINT
DECLARE @TopPercent FLOAT

-- Given that there is an Sequential Identity Column
-- Limit query to only rows in the most recent TOP 5% of rows
SET @TopPercent = .05
SELECT @RowIdTableA = (MAX(TableAId) - (MAX(TableAId) * @TopPercent)) FROM TableA
SELECT @RowIdTableB = (MAX(TableBId) - (MAX(TableBId) * @TopPercent)) FROM TableB

SELECT *
FROM TableA a
INNER JOIN TableB b ON a.KeyId = b.KeyId
WHERE a.Id > @RowIdTableA AND b.Id > @RowIdTableB AND
      a.SomeOtherCriteria = 'Whatever'
CodeCowboyOrg
sumber
-1

Untuk menampilkan 3 baris terakhir tanpa menggunakan order by:

select * from Lms_Books_Details where Book_Code not in 
 (select top((select COUNT(*) from Lms_Books_Details ) -3 ) book_code from Lms_Books_Details) 
abhinay
sumber
1
Ini tidak akan memberikan hasil yang dapat diprediksi. Menurut dokumen MSDN Server Sql ( msdn.microsoft.com/en-us/library/ms189463.aspx ): "Ketika TOP digunakan bersama dengan klausa ORDER BY, kumpulan hasil dibatasi ke nomor N pertama yang dipesan baris; jika tidak, ini mengembalikan N baris pertama dalam urutan yang tidak ditentukan. "
caveman_dick
-1

Coba gunakan EXCEPTsintaks.
Sesuatu seperti ini:

   SELECT * 
    FROM   clientDetails 
    EXCEPT 
    (SELECT TOP (numbers of rows - how many rows you want) * 
     FROM   clientDetails) 
mayur godhani
sumber
Jawaban yang sama dengan @Prafulla Sutradhar
DMK
-1

Mungkin agak terlambat, tetapi berikut ini adalah pilihan sederhana yang menjawab pertanyaan Anda.

SELECT * FROM "TABLE" T ORDER BY "T.ID_TABLE" DESC LIMIT 5;
Lucas Orso
sumber