How to get the first and last record from a SQL query?

I have a table in PostgreSQL , I run a query on it with several conditions that return multiple rows ordered by one of the columns. In general, these are:

SELECT <some columns> FROM mytable <maybe some joins here> WHERE <various conditions> ORDER BY date DESC 

Now I'm only interested in getting the first and last line from this query. I could get them outside of db, inside my application (and this is what I actually do), but it was interesting if for best performance I should not get from the database only those 2 records that really interest me.

And if so, how can I change my request?

+42
sql postgresql
Sep 28 '09 at 4:16
source share
10 answers

[Caution: this may not be the most effective way to do this):

 (SELECT <some columns> FROM mytable <maybe some joins here> WHERE <various conditions> ORDER BY date DESC LIMIT 1) UNION ALL (SELECT <some columns> FROM mytable <maybe some joins here> WHERE <various conditions> ORDER BY date ASC LIMIT 1) 
+53
Sep 28 '09 at 4:23
source share

First recording:

 SELECT <some columns> FROM mytable <maybe some joins here> WHERE <various conditions> ORDER BY date ASC LIMIT 1 

Last record:

 SELECT <some columns> FROM mytable <maybe some joins here> WHERE <various conditions> ORDER BY date DESC LIMIT 1 
+19
Sep 28 '09 at 4:26
source share

You might want to try this, perhaps faster than two queries:

 select <some columns> from ( SELECT <some columns>, row_number() over (order by date desc) as rn, count(*) over () as total_count FROM mytable <maybe some joins here> WHERE <various conditions> ) t where rn = 1 or rn = total_count ORDER BY date DESC 
+18
Aug 26 2018-12-21T00:
source share

last record:

 SELECT * FROM `aboutus` order by id desc limit 1 

First recording:

 SELECT * FROM `aboutus` order by id asc limit 1 
+12
03 Sep '12 at 6:19 06:19
source share
 SELECT * FROM TABLE_NAME WHERE ROWID=(SELECT MIN(ROWID) FROM TABLE_NAME) UNION SELECT * FROM TABLE_NAME WHERE ROWID=(SELECT MAX(ROWID) FROM TABLE_NAME) 

or

 SELECT * FROM TABLE_NAME WHERE ROWID=(SELECT MIN(ROWID) FROM TABLE_NAME) OR ROWID=(SELECT MAX(ROWID) FROM TABLE_NAME) 
+4
Aug 26 2018-12-18T00:
source share

In all open methods, you still need to scan twice, one for the first line and one for the last line.

Using the window function "ROW_NUMBER () OVER (...)" plus "WITH Queries", you can scan only once and get both items.

Window Function: https://www.postgresql.org/docs/9.6/static/functions-window.html

With requests: https://www.postgresql.org/docs/9.6/static/queries-with.html

Example:

 WITH scan_plan AS ( SELECT <some columns>, ROW_NUMBER() OVER (ORDER BY date DESC) AS first_row, /*It logical required to be the same as major query*/ ROW_NUMBER() OVER (ORDER BY date ASC) AS last_row /*It rigth, needs to be the inverse*/ FROM mytable <maybe some joins here> WHERE <various conditions> ORDER BY date DESC) SELECT <some columns> FROM scan_plan WHERE scan_plan.first_row = 1 OR scan_plan.last_row = 1; 

Thus, you will do relationships, filtering and data processing only once.

Try using EXPLAIN ANALYZE in both directions.

+3
Sep 13 '17 at 22:41
source share
 select * from {Table_Name} where {x_column_name}=( select d.{x_column_name} from ( select rownum as rno,{x_column_name} from {Table_Name})d where d.rno=( select count(*) from {Table_Name})); 
+1
Jan 14 '13 at 15:56
source share
 SELECT MIN(Column), MAX(Column), UserId FROM Table_Name WHERE (Conditions) GROUP BY UserId DESC 

or

 SELECT MAX(Column) FROM TableName WHERE (Filter) UNION ALL SELECT MIN(Column) FROM TableName AS Tablename1 WHERE (Filter) ORDER BY Column 
0
Dec 01 '16 at 12:30
source share
 -- Create a function that always returns the first non-NULL item CREATE OR REPLACE FUNCTION public.first_agg ( anyelement, anyelement ) RETURNS anyelement LANGUAGE SQL IMMUTABLE STRICT AS $$ SELECT $1; $$; -- And then wrap an aggregate around it CREATE AGGREGATE public.FIRST ( sfunc = public.first_agg, basetype = anyelement, stype = anyelement ); -- Create a function that always returns the last non-NULL item CREATE OR REPLACE FUNCTION public.last_agg ( anyelement, anyelement ) RETURNS anyelement LANGUAGE SQL IMMUTABLE STRICT AS $$ SELECT $2; $$; -- And then wrap an aggregate around it CREATE AGGREGATE public.LAST ( sfunc = public.last_agg, basetype = anyelement, stype = anyelement ); 

Got it from here: https://wiki.postgresql.org/wiki/First/last_(aggregate)

0
Apr 14 '17 at 19:19
source share

why not use asc 1 limit order and desc 1 limit order desc 1 ..

?

-one
Feb 23 '16 at 11:23
source share



All Articles