1

I'm using Postgres 9.6.*

I have this:

street | first_name | last_name
1st    | james      | bond
1st    | mr         | q 
1st    | ms         | m
2nd    | man        | with_golden_gun

I would like to get a list of distinct addresses and the first set of 'first_name' and 'last_name' for each.

my desired output:

street | first_name | last_name
1st    | james      | bond
2nd    | man        | with_golden_gun

I am grouping by street, and trying MIN(first_name) and MIN(last_name) -- however -- using MIN there are cases for each group of unique street I can get seemingly random a mix-and-match first_name and last_name that may not be of the same row. Obviously, MIN (minimum) isn't the right aggregator function here.

my question: how do I enforce that the first_name and last_name are from the same row?

Mureinik
  • 297,002
  • 52
  • 306
  • 350
JasonGenX
  • 4,952
  • 27
  • 106
  • 198

4 Answers4

1

You can use the row_number window function to query a single line per group:

SELECT street, first_name, last_name
FROM   (SELECT street, first_name, last_name,
               ROW_NUMBER() OVER (PARTITION BY street ORDER BY first_name) AS rn
        FROM   mytable) t
WHERE  rn = 1
Mureinik
  • 297,002
  • 52
  • 306
  • 350
1

You need the "DISTINCT ON" clause, but this requires sorting, e.g. first_name:

SELECT
 DISTINCT ON (street)
 street, first_name, last_name
FROM table
ORDER BY street, first_name
OBi
  • 106
  • 1
  • 4
0

-- I am grouping this based on min first_name and getting the last name based on that first name

Select street, first_name, 
(select last_name from person o where o.first_name = x.first_name) 
from (Select street, min(first_name) as first_name  
from person v group by street) as x;

-- Output

street | first_name | last_name
-------------------------------------
1st    | james      | bond
2nd    | man        | with_golden_gun

-- If it is okay to combine first name and last name field

Select street, min(concat(first_name , ' ' , last_name)) as name
from person group by street

-- Output

street | name 
----------------------------
1st    | james bond
2nd    | man with_golden_gun
-1

As described in How to show row numbers in PostgreSQL query? you can get a row number. Then you can ORDER or WHERE your select statement as desired.

less
  • 699
  • 6
  • 25
  • wasn't my downvote, but guessing that your answer here is best as a comment. Linking to another answer and saying go look there is my answer is generally bad form. Answers should stand on their own, links to support. – Twelfth Oct 12 '17 at 19:16