แถวสุดท้ายของ SQL Server SELECT N


139

นี่เป็นคำถามที่ทราบ แต่วิธีแก้ปัญหาที่ดีที่สุดที่ฉันพบคือ:

SELECT TOP N *
FROM MyTable
ORDER BY Id DESC

ฉันมีตารางที่มีแถวจำนวนมาก ไม่ใช่ความเป็นไปได้ที่จะใช้คิวรีนั้นเนื่องจากใช้เวลานาน ดังนั้นฉันจะเลือกแถวสุดท้ายได้อย่างไรโดยไม่ต้องใช้ ORDER BY

แก้ไข

ขออภัยคำถามซ้ำซ้อนกับคำถามนี้


"last N" มีความหมายอย่างไร หากไม่มีคำสั่ง "last N" ก็ไม่สมเหตุสมผลนัก หากคุณหมายถึง "last N to insert" ดังนั้นคุณไม่สามารถใช้ SQL Server เพื่อมอบสิ่งนี้ให้คุณได้คุณต้องใช้คำสั่งย่อย ORDER BY
Daniel Renshaw

@Daniel Renshaw: N สุดท้ายของตารางโดยไม่บังคับให้ SQL Server สั่งทุกโต๊ะเพราะมันช้ามากจริงๆ
Diego

แบบสอบถามในคำถามของคุณเป็นวิธีที่ดีที่สุด หากidมีการจัดทำดัชนีแล้วมันจะสแกนดัชนีนั้นในสิ่งที่ตรงกันข้ามและหยุดหลังจาก 5 แถวแรก หากไม่ได้จัดทำดัชนีคุณจะต้องTOP Nเรียงลำดับ สิ่งนี้จะไม่เลวร้ายไปกว่าวิธีอื่น ๆ ไม่จัดเรียงทั้งตาราง (แม้ว่าจะต้องสแกนทั้งตาราง)
Martin Smith

คำตอบ:


38

คุณสามารถทำได้โดยใช้หมายเลขแถวตามคุณสมบัติเช่นกัน ตัวอย่างที่ดีสามารถพบได้ที่นี่ :

ฉันกำลังใช้ตารางคำสั่งซื้อของฐานข้อมูล Northwind ... ตอนนี้ให้เราดึงข้อมูลคำสั่งซื้อ 5 รายการล่าสุดจากพนักงาน 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
คุณลักษณะ PARTITION ลำดับเลขจำแนกตามการใช้การจัดเรียงเช่นกัน .. คุณจำเป็นต้องเรียงลำดับตารางไปยังหมายเลขแถวกำหนดสำหรับแต่ละระเบียน ...
Sadhir

นี่เป็นความจริง แต่หากไม่มีลักษณะบางอย่างสิ่งนี้ก็ไม่ได้ผลวิธีที่ดีที่สุดคือการจัดทำดัชนีคอลัมน์หลักที่มีการเข้าชมและเรียกใช้ด้วยบางสิ่งเช่นข้อความค้นหาด้านบน
JonVD

101

คุณสามารถสร้างเซิร์ฟเวอร์ SQL เพื่อเลือกแถว N แถวสุดท้ายโดยใช้ SQL นี้:

select * from tbl_name order by id desc limit N;

2
ความเข้ากันได้กับรุ่นได้อย่างไร
Fractaliste

63
สิ่งนี้ไม่ทำงานใน SQL Server ดูเหมือนว่าฟีเจอร์ MySQL, PostgreSQL และ SQLite
Tim Friesen

3
ผลิตภัณฑ์ที่แจกแจงทั้งหมดเป็นเซิร์ฟเวอร์ SQL ที่แน่นอน ถ้าคุณต้องการพูดคุยเกี่ยวกับเซิร์ฟเวอร์ MS SQL ทำไมไม่ตั้งชื่อมัน
gena2x

4
ฉันสับสนคำถามจะถามวิธีสร้างแบบสอบถามแบบใช้เลือกข้อมูล "โดยไม่ใช้ ORDER BY" และแบบสอบถามแบบใช้เลือกข้อมูลในคำตอบของคุณมี "เรียงตาม" นี่คือ "สั่งซื้อโดย" โดยไม่ต้อง "สั่งโดย"?
Robert Sinclair

5
@ gena2x คำถามนี้ถูกติดแท็ก SQL Server แท็กนั้นอ้างถึง Microsoft SQL Server
Martin Smith

51

ฉันทดสอบโค้ดของ JonVD แต่พบว่าช้ามาก 6s

รหัสนี้ใช้เวลา 0 วินาที

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

4
มีกี่แถว ?? เมื่อคุณมีจำนวนมากของแถวที่สามารถช้าจริง
Diego

@Diego ทำไมเป็นอย่างนั้น? หากคุณได้รับการOrderDateจัดทำดัชนีคุณควรเลือกแถวแรกหรือแถวสุดท้ายของแบบสอบถามอย่างรวดเร็วไม่แพ้กัน ฉันรู้ว่ามีโอกาสที่จะOrderDateสัมพันธ์กับการสั่งซื้อแทรกได้ดี แต่นั่นเป็นผลข้างเคียงที่ดีที่สุดและยังต้องใช้การสแกนตารางใช่ไหม (และผมไม่คิดว่ามันเป็นคำตอบในสิ่งที่จุด OP ว่าล่อเรียบเรียงที่ดีขึ้นของพวกเขาคำถาม : คือไม่เรียงลำดับ)
รัฟฟิน

1
@Diego - ทำไมคุณถึงเชื่อว่าสิ่งนี้จะช้ากว่าคำตอบที่คุณตอบ?
Martin Smith

2
สิ่งนี้จะคืนค่าแถวกลับหัว จากนั้นคุณต้องสั่งซื้อใหม่อีกครั้งเพื่อให้ได้รับคำสั่งซื้อเดิมกลับคืน
ทำเครื่องหมาย

15

หากคุณต้องการเลือกจำนวนแถวสุดท้ายจากตาราง

ไวยากรณ์จะเป็นเช่นนั้น

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

งบเหล่านี้ทำงาน แต่วิธีที่แตกต่าง ขอบคุณทุกคน.

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

ด้วยวิธีนี้คุณจะได้รับ 10 แถวสุดท้าย แต่การสั่งซื้อจะแสดงแบบเรียงลำดับ

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

ในวิธีทั่วไปและสนับสนุนเซิร์ฟเวอร์ SQL ที่นี่คือ

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

และสำหรับประสิทธิภาพก็ไม่เลว (น้อยกว่าหนึ่งวินาทีสำหรับมากกว่า 10,000 บันทึกบนเครื่อง Server)


1
ดี 10,000 บันทึกเป็นอะไรที่คุณควรคำนึงถึงประสิทธิภาพ เมื่อคุณเริ่มพูดถึงบันทึกนับล้านกว่าที่คุณสามารถเริ่มคิดเกี่ยวกับประสิทธิภาพ
Dom84

6

ทำดัชนี "Id" หรือไม่ ถ้าไม่ใช่นั่นเป็นสิ่งสำคัญที่ต้องทำ (ฉันสงสัยว่ามันถูกจัดทำดัชนีแล้ว)

นอกจากนี้คุณต้องส่งกลับคอลัมน์ทั้งหมดหรือไม่ คุณอาจได้รับการปรับปรุงความเร็วอย่างมากถ้าคุณต้องการเพียงส่วนย่อยของคอลัมน์ที่เล็กกว่าซึ่งสามารถจัดทำดัชนีดัชนีคอลัมน์ ID ได้อย่างเต็มที่เช่นถ้าคุณมีดัชนี NONCLUSTERED ในคอลัมน์ Id โดยไม่มีอื่น ๆ เขตข้อมูลที่รวมอยู่ในดัชนีจากนั้นจะต้องทำการค้นหาในดัชนีคลัสเตอร์เพื่อให้ได้คอลัมน์ที่เหลือเพื่อกลับมาจริงและอาจทำให้ค่าใช้จ่ายของแบบสอบถามมากขึ้น หากเป็นดัชนีแบบ CLUSTERED หรือดัชนีแบบ NONCLUSTERED ที่มีเขตข้อมูลอื่น ๆ ทั้งหมดที่คุณต้องการส่งคืนในแบบสอบถามคุณควรจะใช้ได้


6

ครั้งแรกที่คุณได้รับการบันทึกมากที่สุด

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

แล้ว:

ใน SQL Server 2012

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

ใน 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

นี่คือสิ่งที่คุณสามารถลองได้โดยไม่ต้องมีorder byแต่ฉันคิดว่ามันต้องการให้แต่ละแถวไม่ซ้ำกัน Nคือจำนวนแถวที่คุณต้องการLคือจำนวนแถวในตาราง

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

ตามที่ระบุไว้ก่อนหน้าแถวใดที่ถูกส่งคืนจะไม่ถูกกำหนด

แก้ไข: นี่คือสุนัขช้าจริง ๆ ไม่มีคุณค่าจริงๆ



2

แบบสอบถามนี้ส่งคืนแถว N สุดท้ายตามลำดับที่ถูกต้อง แต่ประสิทธิภาพไม่ดี

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


1

สิ่งนี้อาจไม่เหมาะสมกับคำถาม แต่ ...

ส่วนคำสั่ง OFFSET

OFFSET numberข้อช่วยให้คุณสามารถข้ามมากกว่าจำนวนของแถวแล้วกลับแถวหลังจากนั้น

ลิงก์ doc นั้นคือ Postgres ฉันไม่รู้ว่าสิ่งนี้ใช้ได้กับ 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 ไม่รองรับ LIMIT ใน t-sql ส่วนใหญ่ฉันเพิ่งได้รับ MAX (ID) แล้วลบออก

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

สิ่งนี้จะส่งกลับน้อยกว่า 10 ระเบียนเมื่อ ID ไม่ได้เรียงตามลำดับ


0

เทคนิคที่ฉันใช้เพื่อค้นหาแถวล่าสุดที่สุดในตารางที่มีขนาดใหญ่มาก(100+ ล้านหรือ 1+ พันล้านแถว)กำลัง จำกัด คิวรี่ให้ "อ่าน" เฉพาะเปอร์เซ็นต์ "N" ล่าสุดของแถวล่าสุด นี่คือแอปพลิเคชันในโลกแห่งความเป็นจริงตัวอย่างเช่นฉันทำเช่นนี้สำหรับข้อมูลสภาพอากาศล่าสุดที่ไม่ใช่ข้อมูลประวัติศาสตร์หรือค้นหาฟีดข่าวล่าสุดหรือข้อมูลจุดข้อมูลตำแหน่ง GPS ล่าสุด

นี่คือการปรับปรุงประสิทธิภาพอย่างมากถ้าคุณรู้ว่าแถวของคุณอยู่ในอันดับ 5% ล่าสุดของตารางเช่น แม้ว่าจะมีดัชนีอยู่ในตาราง แต่ก็จำกัดความเป็นไปได้ที่จะมีเพียง 5% ของแถวในตารางที่มี 100 + ล้านหรือ 1 + พันล้านแถว โดยเฉพาะอย่างยิ่งกรณีที่ข้อมูลเก่าจะต้องอ่านดิสก์ทางกายภาพและไม่เพียง แต่อ่านLogical In Memoryเท่านั้น

สิ่งนี้มีประสิทธิภาพมากกว่า SELECT TOP | PERCENT | LIMIT เนื่องจากไม่ได้เลือกแถว แต่เพียง จำกัด ส่วนของข้อมูลที่จะค้นหา

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

หากต้องการแสดง 3 แถวสุดท้ายโดยไม่ใช้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
สิ่งนี้จะไม่ให้ผลลัพธ์ที่คาดการณ์ได้ ตามเอกสาร Sql Server MSDN ( msdn.microsoft.com/en-us/library/ms189463.aspx ): "เมื่อใช้ TOP ร่วมกับส่วนคำสั่ง ORDER BY ชุดผลลัพธ์จะถูก จำกัด จำนวน N อันดับแรกของการสั่งซื้อ แถวมิฉะนั้นจะส่งคืนจำนวนแถว N แรกในลำดับที่ไม่ได้กำหนด "
caveman_dick

-1

ลองใช้EXCEPTไวยากรณ์
บางสิ่งเช่นนี้

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

คำตอบเดียวกับ @Prafulla Sutradhar
DMK

-1

อาจจะสายไปซักหน่อย แต่นี่เป็นตัวเลือกง่ายๆที่ตอบคำถามของคุณ

SELECT * FROM "TABLE" T ORDER BY "T.ID_TABLE" DESC LIMIT 5;
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.