Kaip pasirinkti SQL duomenų bazės lentelės n-ąją eilutę?

Mane domina kai kurios (idealios) agnostikų būdų duomenų bazės, leidžiančios pasirinkti duomenų bazės lentelės n-ąją eilutę, tyrimas. Taip pat būtų įdomu žinoti, kaip tai galima pasiekti naudojant integruotą šių duomenų bazių funkciją:

  • „SQL Server“
  • MySQL
  • PostgreSQL
  • Sqlite
  • „Oracle“

„SQL Server 2005“ veikiau kažką panašaus: bet norėčiau pamatyti kitus agnostinius metodus:

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

Kreditas už aukščiau minėtą SQL: „ Firoz Ansari“ tinklaraštį

Atnaujinimas: žr. „ Troels Arvin“ atsakymą dėl SQL standarto. Troels, ar turite kokių nors nuorodų?

279
19 авг. nustatė Charles Roper 19 rug. 2008-08-19 20:13 '08 at 8:13 pm 2008-08-19 20:13
@ 27 atsakymai

Yra būdų tai padaryti pasirinktose standarto dalyse, tačiau daugelis duomenų bazių palaiko savo būdą tai padaryti.

Labai gera svetainė, kurioje kalbama apie tai ir kitus dalykus, http://troels.arvin.dk/db/rdbms/#select-limit .

Iš esmės „PostgreSQL“ ir „MySQL“ palaiko nestandartinius:

 SELECT... LIMIT y OFFSET x 

„Oracle“, „DB2“ ir „MSSQL“ palaiko standartines >

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

(kurią aš tiesiog nukopijau iš anksčiau susietos svetainės, nes aš niekada nenaudoju šių duomenų bazių)

Atnaujinimas: „PostgreSQL 8.4“ palaiko standartines >

250
19 авг. Henrik Gustafsson atsakymas 19 rug. 2008-08-19 22:22 '08, 22:22 pm 2008-08-19 22:22

LIMIT / OFFSET sintaksė PostgreSQL :

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

Šiame pavyzdyje pasirinkta 21 eilutė. OFFSET 20 sako „Postgres“ praleisti pirmuosius 20 įrašų. Jei nenurodysite ORDER BY , nėra jokių garantijų, kokie įrašai bus grąžinti, o tai retai naudinga.

Matyt, SQL standartas tylėjo apie problemą, susijusią su beprotingų >

65
19 авг. atsakymas pateikiamas Neall 19 rug . 2008-08-19 20:31 '08 at 8:31 pm 2008-08-19 20:31

Aš nesu tikras dėl bet kurio kito, bet žinau, kad SQLite ir MySQL neturi numatyto eilės eilės. Šiuose dviejuose dialektuose bent jau šis fragmentas fiksuoja 15-ąjį įrašą iš lentelės, surūšiuotą pagal datą / laiką, kai jis buvo pridėtas:

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

(Žinoma, turėsite pridėti pridėtą DATETIME lauką ir nustatyti datą / laiką, kada šis įrašas buvo pridėtas ...)

21
19 авг. atsakymą pateikė Ellen Teapot 19 rug. 2008-08-19 20:20 '08 at 20:20 pm 2008-08-19 20:20

Įtariu, kad tai yra nepaprastai neveiksminga, tačiau tai gana paprastas požiūris, kuris dirbo su nedideliu duomenų rinkiniu, kuriame bandžiau.

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

Tai bus penktas elementas, pakeiskite antrąjį viršų skaičių, kad gautumėte dar vieną n punktą

Tik „SQL Server“ (manau), bet turėtų veikti senesnėse versijose, kurios nepalaiko ROW_NUMBER ().

16
19 авг. Tim Saunders atsakymas, rugpjūčio 19 d 2008-08-19 20:28 '08 at 8:28 pm 2008-08-19 20:28

SQL 2005 ir naujesnėje versijoje yra integruota funkcija. Naudokite funkciją ROW_NUMBER (). Tai puikiai tinka interneto puslapiams su <Ankstesnis. Ir toliau → naršyti stilių:

Sintaksė:

 SELECT * FROM ( SELECT ROW_NUMBER () OVER (ORDER BY MyColumnToOrderBy) AS RowNum, * FROM Table_1 ) sub WHERE RowNum = 23 
15
09 июля '09 в 18:00 2009-07-09 18:00 Atsakymą pateikė Ben Breen liepos 9 d. 09 val. 18:00 val. 2009-07-09 18:00

1 nedidelis pakeitimas: n-1 vietoj n.

 select * from thetable limit n-1, 1 
11
19 авг. Nick Berardi atsakymas rugpjūčio 19 d 2008-08-19 22:25 '08 10:25 val. 2008-08-19 22:25

Patikrinkite jį „SQL Server“:

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

Tai suteiks jums dešimties eilutės „Emp“ lentelę!

9
16 окт. atsakymas, kurį pateikė Rameshwar Pawale 16 okt. 2014-10-16 13:59 '14, 13:59 2014-10-16 13:59

Skirtingai nei kai kurie atsakymai, SQL standartas nėra tylus dėl šio klausimo.

Naudodami „SQL: 2003“ galite naudoti „>

Ir SQL: 2008 buvo pridėta šiek tiek paprastesnio požiūrio, naudojant
OFFSET skip ROWS FETCH FIRST n ROWS ONLY

Asmeniškai nemanau, kad SQL: 2008 pridėjimas buvo tikrai būtinas, todėl, jei buvau ISO, tai būtų buvęs išlaikęs nuo gana didelio standarto.

7
04 сент. atsakymą pateikė Troels Arvin apie 04 sep . 2008-09-04 01:39 '08 at 1:39 2008-09-04 01:39

SQL SERVER


Pasirinkite viršutinį n. Įrašą.

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

pasirinkite iš n

 SELECT * FROM ( SELECT ID, NAME, ROW_NUMBER() OVER(ORDER BY ID DESC) AS ROW FROM TABLE ) AS TMP WHERE ROW = n 
6
19 февр. atsakymas duotas Aditya 19 vas. 2014-02-19 07:17 '14 at 7:17 2014-02-19 07:17

„Oracle“:

 select * from (select foo from bar order by foo) where ROWNUM = x 
5
19 авг. Mark Harrison atsakymas 19 rug. 2008-08-19 21:51 '08 at 9:51 pm 2008-08-19 21:51

Kai dirbome MSSQL 2000, mes padarėme tai, ką vadinome „trigubu apversti“:

EDITED

 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 

Tai nebuvo elegantiška, ir tai nebuvo greita, bet ji dirbo.

5
19 авг. atsakymą pateikė Adam V 19 rug. 2008-08-19 20:33 '08 at 8:33 pm 2008-08-19 20:33

Čia galite greitai išspręsti jūsų painiavą.

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

Čia galite gauti paskutinę eilutę, užpildydami N = 0, antrąjį - N = 1, ketvirtąjį paskutinį užpildymą N = 3 ir tt

Tai labai dažnas klausimas apie pokalbį, ir tai yra labai paprasti jo aspektai.

Kitas Jei norite, kad suma, identifikatorius arba tam tikras skaitmeninis rūšiavimas viršytų u, galite naudoti „MySQL“ funkciją CAST.

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

Čia, užpildydami N = 4, galite gauti penktąjį naujausią didžiausią sumą iš CART lentelės. Galite įdėti savo lauko pavadinimą ir lentelę ir pateikti sprendimą.

3
17 мая '12 в 12:29 2012-05-17 12:29 atsakė Amitui Šachui gegužės 17 d., 12 val. 12:29 2012-05-17 12:29

Pridėti:

 LIMIT n,1 

Tai apribos rezultatus vienu rezultatu, pradedant nuo rezultato n.

2
19 авг. Andrew G. Johnson atsakymas 19 rug. 2008-08-19 20:14 '08 at 8:14 pm 2008-08-19 20:14

LIMIT n, 1 neveikia MS SQL Server. Manau, tai tik vienintelė pagrindinė duomenų bazė, kuri nepalaiko šios sintaksės. Kad būtų sąžininga, ji nėra SQL standarto dalis, nors taip plačiai remiama, kad ji turėtų būti. Viskas, išskyrus SQL Server LIMIT, veikia gerai. „SQL Server“ nerado elegantiško sprendimo.

2
19 авг. Atsakymas pateikiamas Kibbee 19 rug. 2008-08-19 20:18 '08 8:18 pm 2008-08-19 20:18

Bet iš tikrųjų, ar ne visa tai tikrai tik keletas puikių gudrybių geram duomenų bazės dizainui? Keletą kartų man reikėjo tokios funkcijos, kad tai buvo paprasta užklausa greitai pateikti ataskaitą. Bet kokiam tikram darbui, naudojant tokius triukus, kyla problemų. Jei norite pasirinkti tam tikrą eilutę, tiesiog įveskite stulpelį su nuosekliąja verte ir atlikite su juo.

2
19 авг. John Dyer atsakymas rugpjūčio 19 d 2008-08-19 22:06 '08 22:06 val. 2008-08-19 22:06

Čia yra bendroji „Sproc“ versija, kurią neseniai parašiau „Oracle“, kuri leidžia dinaminį ieškos / rūšiavimą - 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
19 авг. Greg Hurlman atsakymas 19 rug . 2008-08-19 20:19 '08 at 8:19 pm 2008-08-19 20:19

Pavyzdžiui, jei norite pasirinkti kiekvieną 10-ąją eilutę MSSQL, galite naudoti;

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

Tiesiog paimkite MOD ir pakeiskite skaičių 10 į norimą numerį.

2
30 дек. Atsakymą pateikė EA 30 d. 2011-12-30 11:41 '12, 11:41, 2011-12-30 11:41

SQL serveryje bendras maršruto eilutės numeris yra: SET ROWCOUNT @row - @row = eilutės numeris, kurį norite dirbti.

Pavyzdys:

20 eilutėje nustatoma eilutė - nustato eilutę į 20 eilutę

pasirinkite mėsą, sūrį iš dbo.sandwich - pasirinkite stulpelius iš 20 eilutės lentelės

Nustatyti 0 eilutės eilutę - nustato eilutę atgal į visas eilutes

Tai grąžins informaciją apie 20 eilutę. Būtinai įveskite reikšmę 0 po.

Žinau neobišką, bet aš esu „SQL noob“, ir aš jį naudoju, ką aš galiu pasakyti?

1
22 июня '09 в 20:00 2009-06-22 20:00 Atsakymą pateikė Eric birželio 22 d. 09:00 val. 2009-06-22 20:00

„Sybase SQL Anywhere“:

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

Nepamirškite ORDER BY arba jis yra beprasmis.

1
19 авг. Graeme Perrow atsakymas 19 rug. 2008-08-19 22:06 '08 22:06 val. 2008-08-19 22:06
 SELECT * FROM emp a WHERE n = (SELECT COUNT( _rowid) FROM emp b WHERE a. _rowid >= b. _rowid); 
1
08 июня '09 в 20:10 2009-06-08 20:10 atsakymą pateikė Rahul Sharma, birželio 08, 09, 20:10, 2009-06-08 20:10

T-SQL - iš lentelės pasirinkite 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 

Pavyzdžiui, norėdami pasirinkti penktą įrašą iš Darbuotojų lentelės, jūsų užklausa turi būti

 select * from (select row_number() over (order by Rand() desc) as Rno,* from Employee) T where T.Rno = 5 
1
19 нояб. Atsakymą pateikė Sangeeth Krišna lapkričio 19 d 2010-11-19 22:02 '10 10:02 val. 2010-11-19 22:02
 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 

Užrašiau šią užklausą, kad surastumėte N-ąją eilutę. Šis užklausos pavyzdys būtų

 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 
1
29 янв. atsakymą pateikė Arjun Chiddarwar sausio 29 d 2015-01-29 12:09 '15 - 12:09 2015-01-29 12:09

Nieko neįprasto, jokių specialių funkcijų, jei naudojate „Caché“, kaip ir aš ...

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

Jei turite identifikatoriaus arba duomenų žyma, kurią galite pasitikėti.

0
01 окт. Scott Beeson atsakymas spalio 01 d 2015-10-01 16:16 '15, 16:16 2015-10-01 16:16

Taigi aš tai padarysiu DB2 SQL, manau, kad RRN (santykinis įrašų skaičius) yra saugomas O / S lentelėje;

 SELECT * FROM ( SELECT RRN(FOO) AS RRN, FOO.* FROM FOO ORDER BY RRN(FOO)) BAR WHERE BAR.RRN = recordnumber 
0
18 нояб. Atsakymą pateikia RDKells 18 lapkritis 2016-11-18 18:12 '16 at 18:12 pm 2016-11-18 18:12

Man atrodo, kad norint, kad būtų veiksmingas, reikia: 1) sukurti atsitiktinį skaičių nuo 0 iki vieno mažiau nei duomenų bazėje įrašytų įrašų skaičius ir 2) sugebėti pasirinkti eilutę šioje pozicijoje. Deja, skirtingose ​​duomenų bazėse yra skirtingi atsitiktinių skaičių generatoriai ir skirtingi būdai, kaip pasirinkti eilutę rezultato rinkinyje - paprastai nurodote, kiek eilučių praleisti ir kiek eilių norite, bet skirtingoms duomenų bazėms tai daroma kitaip. Būtent tai veikia „SQLite“:

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

Tai priklauso nuo galimybės naudoti subquery ribinėje sąlygoje (kuri SQLite yra LIMIT <recs for skipping>, <recs, kad priimtų>) Pasirinkus lentelės įrašų skaičių, turėtų būti ypač veiksminga duomenų bazės metaduomenų dalis, tačiau tai priklauso nuo duomenų bazės įgyvendinimo . Be to, nežinau, ar užklausa iš tikrųjų sukurs rezultato rinkinį prieš gaunant N-tąjį įrašą, bet tikiuosi, kad jis nebus reikalingas. Atkreipkite dėmesį, kad nenurodau „užsakymo pagal“ sąlygos. Gali būti geriau „organizuoti“ kažką panašaus į pirminį raktą, kuris turės indeksą - gauti indeksą iš N-ojo įrašo gali būti greitesnis, jei duomenų bazė negali gauti N-osios įrašo iš pačios duomenų bazės nesukūrusi rezultatų rinkinio.

0
17 июля '17 в 9:33 2017-07-17 09:33 atsakymą pateikė vartotojo1738579 17 liepos 17 d. 9:33 2017-07-17 09:33
 select * from (select * from ordered order by order_id limit 100) x order by x.order_id desc limit 1; 

Pirma, pasirinkite 100 geriausių eilučių, užsakydami jas didėjančia tvarka, tada pasirinkite paskutinę eilutę, užsakydami mažėjančia tvarka ir apribodami iki 1. Tačiau tai yra labai brangus operatorius, kai jis du kartus pasiekia duomenis.

0
02 июня '17 в 23:26 2017-06-02 23:26 atsakymas duotas Dwipam Katariya birželio 2 d. 17, 23:26 2017-06-02 23:26

Tai neįtikėtina, kad galite rasti SQL mechanizmą, kuris vykdo šią funkciją ...

 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
06 марта '09 в 16:30 2009-03-06 16:30 atsakymą pateikė jrEving kovo 06'09 , 16.30 val. 2009-03-06 16:30

Kiti klausimai apie etiketes „ arba Užduoti klausimą