Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

PostgreSQL: Select only the first record per id based on sort order

For the following query I need to select only the first record with the lowest shape_type value (ranges from 1 to 10). If you have any knowledge on how to easily do this is postgresql, please help. Thanks for your time.

select g.geo_id, gs.shape_type
from schema.geo g   
join schema.geo_shape gs on (g.geo_id=gs.geo_id)  
order by gs.shape_type asc;
like image 522
Sarah Bergquist Avatar asked Sep 24 '13 16:09

Sarah Bergquist


People also ask

How do you SELECT the first record in a group by SQL?

First, you need to write a CTE in which you assign a number to each row within each group. To do that, you can use the ROW_NUMBER() function. In OVER() , you specify the groups into which the rows should be divided ( PARTITION BY ) and the order in which the numbers should be assigned to the rows ( ORDER BY ).

How do I limit records in PostgreSQL?

The LIMIT clause can be used with the OFFSET clause to skip a specific number of rows before returning the query for the LIMIT clause. Syntax:SELECT * FROM table LIMIT n OFFSET m; Let's analyze the syntax above. The LIMIT clause returns a subset of “n” rows from the query result.

What is the query to fetch first record from the table?

To get the first and last record, use UNION. LIMIT is also used to get the number of records you want.


1 Answers

PostgreSQL have very nice syntax for this types of queries - distinct on:

SELECT DISTINCT ON ( expression [, ...] ) keeps only the first row of each set of rows where the given expressions evaluate to equal. The DISTINCT ON expressions are interpreted using the same rules as for ORDER BY (see above). Note that the "first row" of each set is unpredictable unless ORDER BY is used to ensure that the desired row appears first.

So your query becomes:

select distinct on(g.geo_id)     g.geo_id, gs.shape_type from schema.geo g        join schema.geo_shape gs on (g.geo_id=gs.geo_id)   order by g.geo_id, gs.shape_type asc; 

In general ANSI-SQL syntax for this (in any RDBMS with window functions and common table expression, which could be switched to subquery) would be:

with cte as (     select         row_number() over(partition by g.geo_id order by gs.shape_type) as rn,         g.geo_id, gs.shape_type     from schema.geo g            join schema.geo_shape gs on (g.geo_id=gs.geo_id)   ) select     geo_id, shape_type from cte where rn = 1 
like image 115
Roman Pekar Avatar answered Sep 24 '22 02:09

Roman Pekar