tags:

views:

649

answers:

3
table {
  id: long
  name: string
}

1235 Fred
1902 Trever
5123 George
6467 Derek
7868 Joe
8972 Bob
9272 Alf
9842 Hank

I want to return 2 records prior to that of Joes, in ascending order.

i.e The correct values should be:

5123 George
6467 Derek

Any thoughts? FYI:

  1. Returns incorrect rows:

    select * from table with id<7868 order by id asc limit 2

  2. Returns incorrect sort order:

    select * from table with id<7868 order by id desc limit 2

+4  A: 
SELECT * FROM
  (select * from table where id<7868 order by id desc limit 2) AS foo
ORDER BY ID ASC
Alex Martelli
Thank you alex. Amazingly enough its supported by SQLite too! :D
Matt
Ah yes, SQLite does nested selects right (as well as much else) -- amazin' little beast, innit!-)
Alex Martelli
It is indeed - although it confuses me that it parses but does not enforce foreign key constraints :)
Matt
now, try this when there are a million (or more) rows, and see if the performance is acceptable - especially on MySQL.
Chii
On a test of my local copy of the database (running on a 2yr old dell desktop) with over 300k records the difference is negligible over a regular sort (both a regular sort by desc and this reversed subquery sort return 0.00 sec in mysql client). Its not a good benchmark by any means, but I would assume the database engine is only having to do an additional sort over the returned rowsfrom the subquery (i.e. pretty much nothing)
Matt
@Matt, @Chii's worry is quite understandable since we've all been burned by absurdly bad nested-select performance in the past (mostly I expect in MySQL), so thanks for benchmarking (and confirming that SQLite does it sensibly!).
Alex Martelli
+1  A: 

Try:

Select * from (
    select * from table with id<7868 
    order by id desc limit 2
) as t order by id asc

Doing the subquery lets you first get the correct rows, then you can re-order them afterwards

Jonathan Fingland
A: 

In PostgreSQL:

select * from "table" where id < 7868 order by id asc limit 2 offset 2

And similarly in MySQL (I believe) "limit 2, 2"

"LIMIT 2 OFFSET 2" works in SQLite too, at least with the version I tried (3.6.13)

araqnid
Although this returns the correct results when using the data given in the question, I'm guessing that data is just a small, trivialised example. Similarly, "SELECT * FROM table WHERE id IN (5123, 6467) ORDER BY id" gives the correct results with the example data, but is useless in the general case.
LukeH
Hi araqnid. Thanks for the response.The offset itself requires knowing the start position of the results we require. Although it works with the data provided, it is not flexible enough for use where we dont know the offset. For example, if I required 3 results, you would need to change the offset to 1. But thanks for your effort!
Matt