Máy chủ SQL CHỌN LẦN N Hàng


139

Đây là một câu hỏi đã biết nhưng giải pháp tốt nhất tôi tìm thấy là một cái gì đó như:

SELECT TOP N *
FROM MyTable
ORDER BY Id DESC

Tôi có một cái bàn có rất nhiều hàng. Nó không phải là một khả năng sử dụng truy vấn đó bởi vì nó tốn rất nhiều thời gian. Vậy làm thế nào tôi có thể làm để chọn N hàng cuối cùng mà không cần sử dụng ORDER BY?

BIÊN TẬP

Xin lỗi, câu hỏi trùng lặp của câu hỏi này


"N cuối" nghĩa là gì? Không có lệnh, "N cuối" không có ý nghĩa nhiều. Nếu bạn có nghĩa là "N cuối cùng được chèn" thì bạn không thể dựa vào SQL Server để cung cấp cho bạn - bạn phải sử dụng mệnh đề ORDER BY.
Daniel Renshaw

@Daniel Renshaw: N cuối cùng của bảng mà không buộc SQL Server phải đặt hàng tất cả các bảng vì nó rất chậm
Diego

Các truy vấn trong câu hỏi của bạn cách tốt nhất. Nếu idđược lập chỉ mục thì nó sẽ chỉ quét ngược lại và dừng lại sau 5 hàng đầu tiên. Nếu nó không được lập chỉ mục thì nó sẽ cần phải thực hiện một TOP Nsắp xếp. Điều này sẽ không tệ hơn bất kỳ cách làm nào khác. Nó không sắp xếp toàn bộ bảng (mặc dù nó sẽ cần quét toàn bộ bảng)
Martin Smith

Câu trả lời:


38

Bạn cũng có thể làm điều đó bằng cách sử dụng tính năng ROW SỐ B BYNG PHẦN. Một ví dụ tuyệt vời có thể được tìm thấy ở đây :

Tôi đang sử dụng bảng Đơn hàng của cơ sở dữ liệu Northwind ... Bây giờ chúng ta hãy lấy 5 đơn hàng cuối cùng được đặt bởi Nhân viên 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

1
Tính năng ROW SỐ THEO
PHẦN TÍNH

Điều này là đúng, nhưng không có một số tính chất đơn giản là điều này sẽ không hoạt động, giải pháp tốt nhất là lập chỉ mục các cột chính được nhấn và chạy với một cái gì đó giống như truy vấn trên.
JonVD

101

Bạn có thể tạo máy chủ SQL để chọn N hàng cuối cùng bằng SQL này:

select * from tbl_name order by id desc limit N;

2
Làm thế nào về khả năng tương thích phiên bản?
Fractaliste

63
Điều này không hoạt động trong SQL Server. Có vẻ như là một tính năng MySQL, PostgreQuery và SQLite.
Tim Friesen

3
Tất cả các sản phẩm được liệt kê là các máy chủ SQL chắc chắn. Nếu bạn muốn nói về máy chủ MS SQL, tại sao không đặt tên như vậy?
gena2x

4
Tôi đang bối rối, câu hỏi hỏi làm thế nào để tạo một truy vấn chọn "mà không cần sử dụng ORDER BY" và truy vấn chọn trong câu trả lời của bạn có "thứ tự theo". Đây có phải là một loại "đặt hàng bởi" mà không "đặt hàng bởi"?
Robert Sinclair

5
@ gena2x câu hỏi này được gắn thẻ SQL Server. Thẻ đó đề cập đến Microsoft SQL Server.
Martin Smith

51

Tôi đã kiểm tra mã của JonVD, nhưng thấy nó rất chậm, 6s.

Mã này mất 0 giây.

SELECT TOP(5) ORDERID, CUSTOMERID, OrderDate    
FROM Orders where EmployeeID=5    
Order By OrderDate DESC

4
Có bao nhiêu hàng ?? Khi bạn có nhiều hàng có thể THỰC SỰ chậm
Diego

@Diego Tại sao vậy? Nếu bạn đã được OrderDatelập chỉ mục, về cơ bản sẽ nhanh chóng như nhau để chọn N hàng đầu tiên hoặc cuối cùng của truy vấn. Tôi nhận thấy có một cơ hội OrderDatetương quan tốt để đặt hàng được chèn, nhưng đó là một tác dụng phụ tốt nhất, và vẫn cần quét bảng, phải không? (Và tôi không nghĩ rằng nó trả lời những gì các điểm OP là một dupe phrased tốt hơn về câu hỏi của họ : ví dụ, mà không phân loại)
ruffin

1
@Diego - Tại sao bạn tin rằng điều này sẽ chậm hơn câu trả lời bạn chấp nhận?
Martin Smith

2
Điều này trả về các hàng lộn ngược. Sau đó, bạn phải đặt hàng lại bởi họ để lấy lại thứ tự ban đầu.
Đánh dấu

15

Nếu bạn muốn chọn số hàng cuối cùng từ một bảng.

Cú pháp sẽ như thế nào

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

Những tuyên bố này hoạt động nhưng cách khác nhau. cảm ơn các bạn.

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

bằng cách này, bạn có thể nhận được 10 hàng cuối cùng nhưng thứ tự sẽ hiển thị cách giảm dần

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)

7

Nói một cách rất chung chung và để hỗ trợ máy chủ SQL ở đây là

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

và về hiệu suất, nó không tệ (chưa đến một giây cho hơn 10.000 bản ghi trên máy chủ)


1
10.000 hồ sơ cũng không có gì đáng để bạn quan tâm về hiệu suất. Khi bạn bắt đầu nói về hàng triệu bản ghi, bạn có thể bắt đầu nghĩ về hiệu suất
Dom84

6

"Id" có được lập chỉ mục không? Nếu không, đó là một điều quan trọng phải làm (tôi nghi ngờ nó đã được lập chỉ mục).

Ngoài ra, bạn có cần trả về TẤT CẢ các cột không? Bạn có thể có được sự cải thiện đáng kể về tốc độ nếu bạn thực sự chỉ cần một tập hợp con cột nhỏ hơn có thể HOÀN TOÀN được phục vụ bởi chỉ mục trên cột ID - ví dụ: nếu bạn có chỉ số NONCLUSTERED trên cột Id, không có chỉ số nào khác các trường được bao gồm trong chỉ mục, sau đó nó sẽ phải thực hiện tra cứu chỉ mục được nhóm để thực sự lấy phần còn lại của các cột để trả về và điều đó có thể chiếm rất nhiều chi phí của truy vấn. Nếu đó là chỉ mục CLUSTERED hoặc chỉ mục NONCLUSTERED bao gồm tất cả các trường khác mà bạn muốn trả về trong truy vấn, thì bạn sẽ ổn.


6

Đầu tiên bạn nhận được số lượng kỷ lục từ

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

Và sau đó :

Trong SQL Server 2012

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

Trong 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 

4

Đây là thứ bạn có thể thử mà không cần order bynhưng tôi nghĩ rằng nó yêu cầu mỗi hàng là duy nhất. Nlà số lượng hàng bạn muốn, Llà số lượng hàng trong bảng.

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

Như đã lưu ý trước đó, hàng nào được trả về là không xác định.

EDIT: đây thực sự là con chó chậm. Không có giá trị thực sự.


4
select * from (select top 6 * from vwTable order by Hours desc) T order by Hours

2

Truy vấn này trả về N hàng cuối theo đúng thứ tự, nhưng hiệu suất của nó kém

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

2

sử dụng desc với orderby ở cuối truy vấn để lấy các giá trị cuối cùng.


1

Điều này có thể không hoàn toàn phù hợp với câu hỏi, nhưng

Mệnh đề OFFSET

Các OFFSET numberkhoản cho phép bạn bỏ qua một số hàng và sau đó trả lại hàng sau đó.

Liên kết doc đó là Postgres; Tôi không biết nếu điều này áp dụng cho Sybase / MS SQL Server.


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

1

MS không hỗ trợ GIỚI HẠN trong t-sql. Hầu hết các lần tôi chỉ nhận được MAX (ID) và sau đó trừ đi.

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

Điều này sẽ trả về ít hơn 10 bản ghi khi ID không tuần tự.


0

Một kỹ thuật tôi sử dụng để truy vấn các hàng RECENT MOST trong các bảng rất lớn (hơn 100 triệu hoặc hơn 1 tỷ hàng) đang giới hạn truy vấn chỉ "đọc" tỷ lệ phần trăm "N" gần đây nhất của ROENT RECENT. Đây là các ứng dụng trong thế giới thực, ví dụ tôi làm điều này cho Dữ liệu thời tiết gần đây không lịch sử hoặc các tìm kiếm nguồn cấp tin tức gần đây hoặc dữ liệu điểm dữ liệu vị trí GPS gần đây.

Đây là một cải tiến hiệu suất rất lớn nếu bạn biết chắc chắn rằng các hàng của bạn nằm trong TOP 5% gần đây nhất của bảng chẳng hạn. Như vậy, ngay cả khi có các chỉ mục trên các Bảng, nó sẽ giới hạn hơn nữa các possibilite chỉ còn 5% số hàng trong các bảng có hơn 100 triệu hoặc hơn 1 tỷ hàng. Điều này đặc biệt xảy ra khi Dữ liệu cũ hơn sẽ yêu cầu đọc Đĩa vật lý và không chỉ đọc logic trong bộ nhớ .

Điều này là hiệu quả hơn so với CHỌN HÀNG ĐẦU | PERCENT | GIỚI HẠN vì nó không chọn các hàng, mà chỉ giới hạn phần dữ liệu cần tìm kiếm.

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'

-1

Để hiển thị 3 hàng cuối mà không sử dụng 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) 

1
Điều này sẽ không cung cấp kết quả dự đoán. Theo tài liệu MSDN của Sql Server ( msdn.microsoft.com/en-us/l Library / ms189463.aspx ): "Khi TOP được sử dụng cùng với mệnh đề ORDER BY, tập kết quả được giới hạn ở số N đầu tiên được đặt hàng hàng, nếu không, nó trả về số N hàng đầu tiên theo thứ tự không xác định. "
caveman_dick

-1

Hãy thử sử dụng EXCEPTcú pháp.
Một cái gì đó như thế này:

   SELECT * 
    FROM   clientDetails 
    EXCEPT 
    (SELECT TOP (numbers of rows - how many rows you want) * 
     FROM   clientDetails) 

Câu trả lời tương tự như @Prafulla Sutradhar
DMK

-1

Có thể hơi muộn, nhưng đây là một lựa chọn đơn giản để giải quyết câu hỏi của bạn.

SELECT * FROM "TABLE" T ORDER BY "T.ID_TABLE" DESC LIMIT 5;
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.