วิธีการเลือกแถวที่ n ในตารางฐานข้อมูล SQL


399

ฉันสนใจที่จะเรียนรู้วิธีฐานข้อมูลแบบไม่เชื่อเรื่องพระเจ้าในการเลือกแถวที่nจากตารางฐานข้อมูล นอกจากนี้ยังเป็นที่น่าสนใจที่จะเห็นว่าสิ่งนี้สามารถทำได้โดยใช้ฟังก์ชั่นพื้นเมืองของฐานข้อมูลต่อไปนี้:

  • เซิร์ฟเวอร์ SQL
  • MySQL
  • PostgreSQL
  • SQLite
  • คำพยากรณ์

ฉันกำลังทำสิ่งต่อไปนี้ใน SQL Server 2005 แต่ฉันสนใจที่จะเห็นแนวทางที่ไม่เชื่อเรื่องพระเจ้าของผู้อื่นมากขึ้น:

WITH Ordered AS (
SELECT ROW_NUMBER() OVER (ORDER BY OrderID) AS RowNumber, OrderID, OrderDate
FROM Orders)
SELECT *
FROM Ordered
WHERE RowNumber = 1000000

เครดิตสำหรับ SQL ข้างต้น: บล็อกของ Firoz Ansari

อัปเดต:ดูคำตอบของ Troels Arvinเกี่ยวกับมาตรฐาน SQL Troels คุณมีลิงค์ที่เราสามารถอ้างอิงได้ไหม?


3
ใช่. นี่คือลิงก์ไปยังข้อมูลเกี่ยวกับมาตรฐาน ISO SQL: troels.arvin.dk/db/rdbms/links/#standards
Troels Arvin

13
เพียงเพื่อชี้ให้เห็นว่าตามคำนิยามของความสัมพันธ์แถวในตารางไม่มีลำดับดังนั้นแถว Nth ในตารางจึงไม่สามารถเลือกได้ สิ่งที่สามารถเลือกได้คือแถวที่ N ในแถวที่ส่งคืนโดยแบบสอบถาม (ส่วนที่เหลือ) ซึ่งเป็นตัวอย่างของคุณและคำตอบอื่น ๆ ทั้งหมดที่ทำได้ มากที่สุดนี่อาจเป็นความหมาย แต่ชี้ไปที่ปัญหาพื้นฐานของคำถาม หากคุณต้องการส่งคืนให้OrderNo Nแนะนำคอลัมน์OrderSequenceNoในตารางและสร้างจากตัวสร้างลำดับอิสระเมื่อสร้างคำสั่งซื้อใหม่
Damir Sudarevic

2
มาตรฐาน SQL offset x fetch first y rows onlyกำหนดตัวเลือก ขณะนี้รองรับ Postgres (อย่างน้อย), Oracle12, DB2
a_horse_with_no_name

คำตอบ:


349

มีวิธีการทำเช่นนี้ในส่วนเสริมของมาตรฐาน แต่ฐานข้อมูลจำนวนมากสนับสนุนวิธีการทำของตัวเอง

เว็บไซต์ที่ดีจริงๆที่พูดเกี่ยวกับเรื่องนี้และสิ่งอื่น ๆ เป็นhttp://troels.arvin.dk/db/rdbms/#select-limit

โดยพื้นฐานแล้ว PostgreSQL และ MySQL รองรับมาตรฐานที่ไม่ได้มาตรฐาน:

SELECT...
LIMIT y OFFSET x 

Oracle, DB2 และ MSSQL รองรับฟังก์ชั่นหน้าต่างมาตรฐาน:

SELECT * FROM (
  SELECT
    ROW_NUMBER() OVER (ORDER BY key ASC) AS rownumber,
    columns
  FROM tablename
) AS foo
WHERE rownumber <= n

(ซึ่งฉันเพิ่งคัดลอกจากเว็บไซต์ที่ลิงก์ด้านบนเนื่องจากฉันไม่เคยใช้ DBs เหล่านั้น)

อัปเดต:ตั้งแต่ PostgreSQL 8.4 รองรับฟังก์ชั่นหน้าต่างมาตรฐานดังนั้นคาดว่าตัวอย่างที่สองจะทำงานกับ PostgreSQL ได้เช่นกัน

ปรับปรุง: SQLite เพิ่มฟังก์ชั่นหน้าต่างรองรับในเวอร์ชั่น 3.25.0 เมื่อวันที่ 2018-09-15 ดังนั้นทั้งสองรูปแบบก็ใช้งานได้ใน SQLite


3
MySQL ใช้ไวยากรณ์ OFFSET และ LIMIT เช่นกัน Firebird ใช้คำหลัก FIRST และ SKIP แต่วางไว้หลังจากเลือก
Doug

7
ไม่ควรที่จะWHERE rownumber = nได้แถวที่ n เท่านั้น?
Steve Bennett

MySQL รองรับฟังก์ชั่นหน้าต่างตั้งแต่รุ่น 8 MariaDB ตั้งแต่รุ่น 10.2
Paul Spiegel

102

PostgreSQL รองรับฟังก์ชั่นหน้าต่างตามที่กำหนดไว้โดยมาตรฐาน SQL แต่มันค่อนข้างงุ่มง่ามดังนั้นคนส่วนใหญ่จึงใช้ (ไม่ใช่แบบมาตรฐาน) LIMIT/OFFSET :

SELECT
    *
FROM
    mytable
ORDER BY
    somefield
LIMIT 1 OFFSET 20;

ตัวอย่างนี้เลือกแถวที่ 21 OFFSET 20กำลังบอกให้ Postgres ข้าม 20 รายการแรก หากคุณไม่ได้ระบุORDER BYข้อใด ๆ คุณจะไม่สามารถรับประกันได้ว่าจะให้บันทึกใดกลับซึ่งมีประโยชน์น้อยมาก


31

ฉันไม่แน่ใจเกี่ยวกับส่วนที่เหลือ แต่ฉันรู้ว่า SQLite และ MySQL ไม่มีการสั่งซื้อแถว "เริ่มต้น" อย่างน้อยสองภาษาตัวอย่างต่อไปนี้คว้ารายการที่ 15 จาก the_table โดยเรียงลำดับตามวันที่ / เวลาที่เพิ่ม:

SELECT * FROM the_table ORDER BY added DESC LIMIT 1,15

(แน่นอนว่าคุณจะต้องมีฟิลด์ DATETIME เพิ่มและตั้งเป็นวันที่ / เวลาที่เพิ่มรายการ ... )


นี่เป็นวิธีที่ดีที่สุดในการ จำกัด คิวรีด้วยค่าออฟเซ็ตอินไลน์ แต่เราไม่ควรใช้ 0,14 ที่นี่หรือ 1,15 จะออกจากแถวแรก
Gladiator

แม้ว่า 15 หมายถึงอะไร ฉันรู้ว่า 1 บอกว่าจะได้รับหนึ่งระเบียน เครื่องหมายจุลภาคที่ไม่ได้ใช้ในตัวอย่างที่ผมตรวจสอบออก1keydata.com/sql/sql-limit.html
committedandroider

1
ที่จริงแล้วจากที่นี่php.about.com/od/mysqlcommands/g/Limit_sql.htmถ้าคุณต้องการที่จะคว้ารายการที่ 15 คุณจะไม่ทำ LIMIT 14, 1 (0 เป็นองค์ประกอบแรก 1 ความยาว
committedandroider

มัน sholud เป็น SELECT * จาก the_table ORDER BY เพิ่ม DESC LIMIT 15,1
JerryGoyal

25

SQL 2005 ขึ้นไปมีฟีเจอร์นี้ในตัว ใช้ฟังก์ชัน ROW_NUMBER () มันยอดเยี่ยมสำหรับเว็บเพจที่มีสไตล์การท่องเว็บ << ก่อนหน้าและถัดไป >>

ไวยากรณ์:

SELECT
    *
FROM
    (
        SELECT
            ROW_NUMBER () OVER (ORDER BY MyColumnToOrderBy) AS RowNum,
            *
        FROM
            Table_1
    ) sub
WHERE
    RowNum = 23

ฉันชอบวิธีนี้มากกว่าเพราะให้ความรู้สึกตรงไปตรงมามากกว่า
FoxArc

18

ฉันสงสัยว่านี่ไม่มีประสิทธิภาพอย่างดุเดือด แต่ก็เป็นวิธีการที่ง่ายซึ่งทำงานบนชุดข้อมูลขนาดเล็กที่ฉันลองใช้

select top 1 field
from table
where field in (select top 5 field from table order by field asc)
order by field desc

รายการนี้จะได้รับรายการที่ 5 เปลี่ยนหมายเลขอันดับสองเพื่อรับรายการที่แตกต่างกัน

เซิร์ฟเวอร์ SQL เท่านั้น (ฉันคิดว่า) แต่ควรทำงานกับรุ่นเก่ากว่าที่ไม่รองรับ ROW_NUMBER ()


ฉันจะใช้สิ่งนี้เนื่องจาก ROW_NUMBER () ไม่ทำงานใน SQL 2000 (ใช่เรามีไคลเอ็นต์บน SQL 2000 ยัง) โดยเฉพาะฉันจะแทนที่ '5' ด้วยตัวแปรตัววนซ้ำของลูปและใช้ ที่จะคัดลอกและแก้ไขแต่ละแถวของตารางในทางกลับกัน บางทีใครบางคนจะเห็นความคิดเห็นนี้และพบว่ามีประโยชน์นี้
Inversus


14

ตรวจสอบบนเซิร์ฟเวอร์ SQL:

Select top 10 * From emp 
EXCEPT
Select top 9 * From emp

นี่จะให้ตารางที่ 10 แถวของคุณ!


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

11

ตรงกันข้ามกับสิ่งที่คำตอบบางคำเรียกร้องมาตรฐาน SQL ไม่ได้เงียบเกี่ยวกับเรื่องนี้

ตั้งแต่ SQL: 2003 คุณสามารถใช้ "ฟังก์ชั่นหน้าต่าง" เพื่อข้ามแถวและชุดผลลัพธ์ที่ จำกัด ได้

และใน SQL: 2008 ได้มีการเพิ่มวิธีที่ง่ายกว่าเล็กน้อยโดยใช้
OFFSET skip ROWS FETCH FIRST n ROWS ONLY

โดยส่วนตัวฉันไม่คิดว่าการเพิ่ม SQL: 2008 นั้นเป็นสิ่งจำเป็นจริง ๆ ดังนั้นถ้าฉันเป็น ISO ฉันจะทำให้มันเป็นมาตรฐานที่ค่อนข้างใหญ่อยู่แล้ว


มันดีที่มีมาตรฐาน แต่ทำให้คนอย่างชีวิตของฉันง่ายขึ้นและ microsoft ก็ทำสิ่งต่าง ๆ ด้วยวิธีมาตรฐาน :)
user230910

7

เมื่อเราเคยทำงานใน MSSQL 2000 เราได้ทำในสิ่งที่เราเรียกว่า "สามทาง":

แก้ไข

DECLARE @InnerPageSize int
DECLARE @OuterPageSize int
DECLARE @Count int

SELECT @Count = COUNT(<column>) FROM <TABLE>
SET @InnerPageSize = @PageNum * @PageSize
SET @OuterPageSize = @Count - ((@PageNum - 1) * @PageSize)

IF (@OuterPageSize < 0)
    SET @OuterPageSize = 0
ELSE IF (@OuterPageSize > @PageSize)
    SET @OuterPageSize = @PageSize

DECLARE @sql NVARCHAR(8000)

SET @sql = 'SELECT * FROM
(
    SELECT TOP ' + CAST(@OuterPageSize AS nvarchar(5)) + ' * FROM
    (
        SELECT TOP ' + CAST(@InnerPageSize AS nvarchar(5)) + ' * FROM <TABLE> ORDER BY <column> ASC
    ) AS t1 ORDER BY <column> DESC
) AS t2 ORDER BY <column> ASC'

PRINT @sql
EXECUTE sp_executesql @sql

มันไม่ได้สวยงามและไม่เร็ว แต่ก็ใช้ได้


สมมติว่าคุณมี 25 แถวและคุณต้องการหน้าสามของ 10 แถวหน้าคือแถว 21-25 แบบสอบถามภายในสุดจะได้รับแถว 30 แถวแรก (1-25 แถว) แบบสอบถามกลางได้รับ 10 แถวสุดท้าย (แถว 25-16) แบบสอบถามด้านนอกจะเรียงลำดับใหม่และส่งคืนแถวที่ 16-25 นี่เป็นความผิดที่ชัดเจนหากคุณต้องการแถวที่ 21-25
Bill Karwin

ตอนนี้มันไม่ทำงานถ้าเราต้องการหน้ากลาง สมมติว่าเรามี 25 แถวและเราต้องการหน้าที่สองเช่นแถว 11-20 คิวรีภายในรับค่าสูงสุด 2 * 10 = 20 แถวหรือแถวที่ 1-20 แบบสอบถามกลางได้รับ 15 แถวสุดท้าย: 25 - ((2-1) * 10) = 15 ซึ่งให้ผลแถว 20-6 คิวรีสุดท้ายย้อนกลับคำสั่งซื้อและส่งคืนแถว 6-20 เทคนิคนี้ใช้งานไม่ได้เว้นแต่ว่าจำนวนแถวทั้งหมดจะเป็นขนาดหน้าที่หลากหลายตามที่คุณต้องการ
Bill Karwin

บางทีข้อสรุปที่ดีที่สุดคือเราควรอัพเกรดอินสแตนซ์ MS SQL Server 2000 ที่เหลืออยู่ :-) เกือบ 2012 และปัญหานี้ได้รับการแก้ไขด้วยวิธีที่ดีกว่าเป็นเวลาหลายปี!
Bill Karwin

@Bill Karwin: สังเกตIF / ELSE IFบล็อกใต้การOuterPageSizeคำนวณ - ในหน้า 1 และ 2 พวกเขาจะลดOuterPageSizeค่ากลับไปที่ 10 ในหน้า 3 (แถว 21-25) การคำนวณจะส่งคืน 5 อย่างถูกต้องและในทุกหน้า 4 และสูงกว่า ผลลัพธ์เชิงลบจากการคำนวณจะถูกแทนที่ด้วย 0 (แม้ว่ามันอาจจะเร็วกว่าที่จะส่งคืนแถวข้อมูลที่ว่างเปล่าทันที ณ จุดนั้น)
Adam V

โอ้ฉันเห็นแล้ว ดีฉันคิดว่าการใช้ MS SQL Server 2000 วันนี้ไม่คุ้มปัญหา
Bill Karwin

6

เซิร์ฟเวอร์ SQL


เลือกระเบียนที่ n จากด้านบน

SELECT * FROM (
SELECT 
ID, NAME, ROW_NUMBER() OVER(ORDER BY ID) AS ROW
FROM TABLE 
) AS TMP 
WHERE ROW = n

เลือกบันทึกจากด้านล่าง

SELECT * FROM (
SELECT 
ID, NAME, ROW_NUMBER() OVER(ORDER BY ID DESC) AS ROW
FROM TABLE 
) AS TMP 
WHERE ROW = n


5

ใน Oracle 12c คุณสามารถใช้OFFSET..FETCH..ROWS ตัวเลือกกับORDER BY

ตัวอย่างเช่นหากต้องการรับระเบียนที่ 3 จากด้านบน:

SELECT * 
FROM   sometable
ORDER BY column_name
OFFSET 2 ROWS FETCH NEXT 1 ROWS ONLY;

4

นี่เป็นวิธีแก้ปัญหาความสับสนของคุณที่รวดเร็ว

SELECT * FROM table ORDER BY `id` DESC LIMIT N, 1

ที่นี่คุณอาจได้รับแถวสุดท้ายโดยการกรอก N = 0, ครั้งที่สองที่ผ่านมาโดย N = 1, ที่สี่ที่ผ่านมาโดยการกรอก N = 3 และอื่น ๆ

นี่เป็นคำถามที่พบบ่อยมากในการสัมภาษณ์และนี่คือคำตอบที่ง่ายมาก

เพิ่มเติมถ้าคุณต้องการจำนวนเงิน, ID หรือคำสั่งการเรียงลำดับตัวเลขบางอย่างที่คุณอาจไปสำหรับฟังก์ชั่น CAST ใน MySQL

SELECT DISTINCT (`amount`) FROM cart ORDER BY CAST( `amount` AS SIGNED ) DESC LIMIT 4 , 1

ที่นี่โดยการกรอก N = 4 คุณจะสามารถรับจำนวนสูงสุดเป็นอันดับที่ห้าจากตาราง CART คุณสามารถใส่ฟิลด์และชื่อตารางของคุณและหาทางแก้ไข


3

เพิ่ม:

LIMIT n,1

ที่จะ จำกัด ผลลัพธ์ไว้ที่ผลลัพธ์หนึ่งรายการโดยเริ่มที่ผลลัพธ์ n


3

ตัวอย่างเช่นหากคุณต้องการเลือกทุกแถวที่ 10 ใน MSSQL คุณสามารถใช้;

SELECT * FROM (
  SELECT
    ROW_NUMBER() OVER (ORDER BY ColumnName1 ASC) AS rownumber, ColumnName1, ColumnName2
  FROM TableName
) AS foo
WHERE rownumber % 10 = 0

เพียงแค่ใช้ MOD และเปลี่ยนหมายเลข 10 ที่นี่หมายเลขใด ๆ ที่คุณต้องการ


3

สำหรับ SQL Server วิธีทั่วไปในการไปตามหมายเลขแถวเป็นเช่นนี้:

SET ROWCOUNT @row --@row = the row number you wish to work on.

ตัวอย่างเช่น:

set rowcount 20   --sets row to 20th row

select meat, cheese from dbo.sandwich --select columns from table at 20th row

set rowcount 0   --sets rowcount back to all rows

นี่จะส่งคืนข้อมูลแถวที่ 20 ตรวจสอบให้แน่ใจว่าได้ใส่หมายเลข 0 ในภายหลัง


2

LIMIT n, 1 ไม่ทำงานใน MS SQL Server ฉันคิดว่ามันเป็นเพียงเกี่ยวกับฐานข้อมูลหลักเท่านั้นที่ไม่สนับสนุนไวยากรณ์นั้น เพื่อความยุติธรรมมันไม่ได้เป็นส่วนหนึ่งของมาตรฐาน SQL แม้ว่าจะได้รับการสนับสนุนอย่างกว้างขวางว่าควรจะเป็น ในทุกสิ่งยกเว้นเซิร์ฟเวอร์ SQL LIMIT ทำงานได้ดี สำหรับเซิร์ฟเวอร์ SQL ฉันไม่สามารถค้นหาโซลูชันที่สวยงามได้


1
ยกเว้น Oracle, DB2 เพียงแค่ฐานข้อมูลระดับองค์กรทุกแห่งในโลก PostgreSQL นั้นเป็นเพียงฐานข้อมูลที่มีความสามารถระดับองค์กรเท่านั้นที่รองรับคีย์เวิร์ด LIMIT และส่วนใหญ่เป็นเพราะโอเพ่นซอร์สจำเป็นต้องเข้าถึงได้จากกลุ่มผู้ใช้ MySQL ที่ไม่รู้วิธี
David

3
@AlexD "คำตอบ" นี้ถูกโพสต์ในสมัยก่อนของ Stackoverflow ก่อนที่ความคิดเห็นจะถูกนำมาใช้ ฉันจะโพสต์สิ่งนี้เป็นความคิดเห็นในคำตอบอื่น แต่ในเวลานั้นความคิดเห็นนั้นไม่มีอยู่จริง
Kibbee

2

นี่เป็นรุ่นทั่วไปของ sproc ที่ฉันเพิ่งเขียนสำหรับ Oracle ที่อนุญาตให้ใช้เพจ / การเรียงลำดับแบบไดนามิก - HTH

-- p_LowerBound = first row # in the returned set; if second page of 10 rows,
--                this would be 11 (-1 for unbounded/not set)
-- p_UpperBound = last row # in the returned set; if second page of 10 rows,
--                this would be 20 (-1 for unbounded/not set)

OPEN o_Cursor FOR
SELECT * FROM (
SELECT
    Column1,
    Column2
    rownum AS rn
FROM
(
    SELECT
        tbl.Column1,
        tbl.column2
    FROM MyTable tbl
    WHERE
        tbl.Column1 = p_PKParam OR
        tbl.Column1 = -1
    ORDER BY
        DECODE(p_sortOrder, 'A', DECODE(p_sortColumn, 1, Column1, 'X'),'X'),
        DECODE(p_sortOrder, 'D', DECODE(p_sortColumn, 1, Column1, 'X'),'X') DESC,
        DECODE(p_sortOrder, 'A', DECODE(p_sortColumn, 2, Column2, sysdate),sysdate),
        DECODE(p_sortOrder, 'D', DECODE(p_sortColumn, 2, Column2, sysdate),sysdate) DESC
))
WHERE
    (rn >= p_lowerBound OR p_lowerBound = -1) AND
    (rn <= p_upperBound OR p_upperBound = -1);

2

แต่จริงๆแล้วทั้งหมดนี้ไม่ใช่แค่ห้องนั่งเล่นสำหรับการออกแบบฐานข้อมูลที่ดีตั้งแต่แรก? ไม่กี่ครั้งที่ฉันต้องการฟังก์ชั่นเช่นนี้มันเป็นคำถามง่ายๆในการสร้างรายงานด่วน สำหรับการทำงานจริงใด ๆ การใช้ลูกเล่นเช่นนี้เป็นการชวนให้ลำบาก หากจำเป็นต้องเลือกแถวใดแถวหนึ่งให้เลือกคอลัมน์ที่มีค่าตามลำดับแล้วเลือกแถวนั้น


2

สำหรับเซิร์ฟเวอร์ SQL ข้อมูลต่อไปนี้จะคืนค่าแถวแรกจากการให้ตาราง

declare @rowNumber int = 1;
    select TOP(@rowNumber) * from [dbo].[someTable];
EXCEPT
    select TOP(@rowNumber - 1) * from [dbo].[someTable];

คุณสามารถวนซ้ำค่าต่างๆดังนี้:

WHILE @constVar > 0
BEGIN
    declare @rowNumber int = @consVar;
       select TOP(@rowNumber) * from [dbo].[someTable];
    EXCEPT
       select TOP(@rowNumber - 1) * from [dbo].[someTable];  

       SET @constVar = @constVar - 1;    
END;

1

ใน Sybase SQL ทุกที่:

SELECT TOP 1 START AT n * from table ORDER BY whatever

อย่าลืมคำสั่งซื้อหรือมันไม่มีความหมาย


1

T-SQL - การเลือก N'th RecordNumber จากตาราง

select * from
 (select row_number() over (order by Rand() desc) as Rno,* from TableName) T where T.Rno = RecordNumber

Where  RecordNumber --> Record Number to Select
       TableName --> To be Replaced with your Table Name

ตัวอย่างเช่นเพื่อเลือกระเบียนที่ 5 จากพนักงานตารางแบบสอบถามของคุณควรเป็น

select * from
 (select row_number() over (order by Rand() desc) as Rno,* from Employee) T where T.Rno = 5


1
SELECT
    top 1 *
FROM
    table_name
WHERE
    column_name IN (
        SELECT
            top N column_name
        FROM
            TABLE
        ORDER BY
            column_name
    )
ORDER BY
    column_name DESC

ฉันเขียนแบบสอบถามนี้เพื่อค้นหาแถวที่ N ตัวอย่างกับแบบสอบถามนี้จะเป็น

SELECT
    top 1 *
FROM
    Employee
WHERE
    emp_id IN (
        SELECT
            top 7 emp_id
        FROM
            Employee
        ORDER BY
            emp_id
    )
ORDER BY
    emp_id DESC

0

ไม่น่าเชื่อว่าคุณสามารถค้นหาเอนจิน SQL ที่รันสิ่งนี้ ...

WITH sentence AS
(SELECT 
    stuff,
    row = ROW_NUMBER() OVER (ORDER BY Id)
FROM 
    SentenceType
    )
SELECT
    sen.stuff
FROM sentence sen
WHERE sen.row = (ABS(CHECKSUM(NEWID())) % 100) + 1

0

ไม่มีอะไรแฟนซีไม่มีฟังก์ชั่นพิเศษในกรณีที่คุณใช้Cachéเหมือนฉัน ...

SELECT TOP 1 * FROM (
  SELECT TOP n * FROM <table>
  ORDER BY ID Desc
)
ORDER BY ID ASC

ระบุว่าคุณมีคอลัมน์ ID หรือคอลัมน์ datestamp ที่คุณสามารถเชื่อถือได้


0

นี่คือวิธีที่ฉันทำภายใน DB2 SQL ฉันเชื่อว่า RRN (หมายเลขระเบียนสัมพันธ์) จะถูกเก็บไว้ในตารางโดย O / S;

SELECT * FROM (                        
   SELECT RRN(FOO) AS RRN, FOO.*
   FROM FOO                         
   ORDER BY RRN(FOO)) BAR             
 WHERE BAR.RRN = recordnumber

0
select * from 
(select * from ordered order by order_id limit 100) x order by 
x.order_id desc limit 1;

อันดับแรกเลือกแถว 100 อันดับแรกโดยเรียงลำดับจากน้อยไปมากแล้วเลือกแถวสุดท้ายโดยเรียงลำดับจากมากไปน้อยและ จำกัด ที่ 1 อย่างไรก็ตามนี่เป็นคำสั่งที่มีราคาแพงมากเนื่องจากเข้าถึงข้อมูลสองครั้ง


0

สำหรับฉันแล้วดูเหมือนว่าเพื่อให้มีประสิทธิภาพคุณต้อง 1) สร้างตัวเลขสุ่มระหว่าง 0 ถึงหนึ่งน้อยกว่าจำนวนระเบียนฐานข้อมูลและ 2) สามารถเลือกแถวที่ตำแหน่งนั้นได้ น่าเสียดายที่ฐานข้อมูลต่าง ๆ มีตัวสร้างตัวเลขสุ่มแตกต่างกันและวิธีต่างๆในการเลือกแถวที่ตำแหน่งในชุดผลลัพธ์โดยปกติแล้วคุณจะระบุจำนวนแถวที่จะข้ามและจำนวนแถวที่คุณต้องการ นี่คือสิ่งที่เหมาะกับฉันใน SQLite:

select * 
from Table 
limit abs(random()) % (select count(*) from Words), 1;

มันขึ้นอยู่กับความสามารถในการใช้แบบสอบถามย่อยในข้อ จำกัด (ซึ่งใน SQLite เป็น LIMIT <recs เพื่อข้าม>, <recs ที่จะใช้>) การเลือกจำนวนของระเบียนในตารางควรมีประสิทธิภาพโดยเฉพาะอย่างยิ่งเป็นส่วนหนึ่งของฐานข้อมูล ข้อมูลเมตา แต่ขึ้นอยู่กับการใช้ฐานข้อมูล นอกจากนี้ฉันไม่ทราบว่าแบบสอบถามจะสร้างชุดผลลัพธ์จริงหรือไม่ก่อนเรียกระเบียน Nth แต่ฉันหวังว่าจะไม่ต้องการ โปรดทราบว่าฉันไม่ได้ระบุคำสั่ง "โดย" มันอาจจะดีกว่าที่จะ "เรียงลำดับตาม" บางอย่างเช่นคีย์หลักซึ่งจะมีดัชนี - รับระเบียน Nth จากดัชนีอาจเร็วกว่าหากฐานข้อมูลไม่สามารถรับบันทึก Nth จากฐานข้อมูลโดยไม่ต้องสร้างชุดผลลัพธ์ .


0

คำตอบที่เหมาะสมที่สุดที่ผมได้เห็นในนี้บทความสำหรับเซิร์ฟเวอร์ SQL

WITH myTableWithRows AS (
    SELECT (ROW_NUMBER() OVER (ORDER BY myTable.SomeField)) as row,*
    FROM myTable)
SELECT * FROM myTableWithRows WHERE row = 3
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.