I have two tables, in PostgreSQL if that matters, with one to many relations. I need to join them so that for each \"one\" I only get single result from the \"many\" table. Not
Simpler, shorter, faster with PostgreSQL's DISTINCT ON
:
SELECT DISTINCT ON (a.id)
a.id, a.name, a.date, b.code1, b.code2
FROM table_a a
LEFT JOIN table_b b USING (id)
ORDER BY a.id, b.sort
Details, explanation, benchmark and links in this closely related answer.
I use a LEFT JOIN
, so that rows from table_a
without any matching row in table_b
are not dropped.
Side notes:
While being allowed in PostgreSQL, it's unwise to use date
as column name. It's a reserved word in every SQL standard and a type name in PsotgreSQL.
It's also an anti-pattern to name an ID column id
. Not descriptive and not helpful. One (of many) possible naming convention would be to name it after the table where it is primary key: table_a_id
. Same name for foreign keys referencing it (if no other natural name takes precedence).
PostgreSQL supports window function. Try this,
SELECT d.ID, d.NAME, d.DATE, d.CODE1, d.CODE2
FROM
(
SELECT a.ID, a.NAME, a.DATE,
b.CODE1, b.CODE2,
ROW_NUMBER() OVER(PARTITION BY a.ID ORDER BY b.SORT ASC, b.CODE2 DESC) AS ROWNUM
FROM TableA a
INNER JOIN TableB b
ON a.ID = b.ID
) d
WHERE d.RowNum = 1
Here's what I'd do on SQL Server.
SELECT a.ID,
a.NAME,
a.DATE,
b.CODE1,
b.CODE2
FROM TABLE_A a
JOIN TABLE_B b
on a.ID = b.ID
WHERE b.SORT = (SELECT MIN(SORT)
FROM TABLE_B
WHERE ID = b.ID)