I have two tables as follows:
create table first (id int, name varchar(20));
create table second (id int, value char(1),fid int);
These tables have the following records:
insert into first values (1,'Ahmad'),(2,'Sami'),(3,'Khan');
insert into second values
(1,'a',1)
, (2,'b',1)
, (3,'c',2)
, (4,'d',1)
, (5,'e',2)
, (6,'f',3);
I want to select those records from table second
which have matching records in table first
in a single row.
The desired output would be:
id | name | value | value | value ---+-------+-------+-------+------- 1 | Ahmad | a | b | d 2 | Sami | c | e | 3 | Khan | f | |
The number of values for a single record of table first
is not limited and there can be n
number of values for a single record of table first
.
n
is unknown, but I need to repeat the column value
for each value in table second
which has matching record in table first
. I need the whole table like above The desired result
. I need only those rows referenced by table second
.
The version of Postgres will be the latest one.
Best Answer
Actually, since
the number of columns to return is not exactly arbitrary. There is a maximum of columns, and this has a clean solution - unless you have more columns than Postgres allows for a table:
BTW, typically, you would also have a
third
table listing all possible values ofvalue
, the whole of it implementing a classical many-to-many relationship.You can use
CASE
statements, or more elegantly, thecrosstab()
function of the additional moduletablefunc
. If you are unfamiliar with it, read basic instructions here first:Columns to the right of actual values are filled with NULL. Assuming a maximum of 5 possible values and building on this setup:
Either use
crosstab(text)
(1 parameter form) and join to tablefirst
another time:Or use
crosstab(text, text)
(2 parameter form) and generate dummy categories for your values:Result is the same either way:
If you want to include all rows from table first, make it a
LEFT [OUTER] JOIN
:Then we get one additional result row for the above example: