0

I have 2 tables that look something like this:

Table A:

CREATE TEMP TABLE table_a (
  ID_number_X text,
  ID_number_Y int
);
INSERT INTO table_a VALUES
  ('HT59452', 123),
  ('HT59453', 123),
  ('HT59454', 123),
  ('HT59455', 789),
  ('HT59456', 101);

Table B:

CREATE TEMP TABLE table_b (
  Column_1 text,
  ID_number_Y int,
  ID_number_X text
);
INSERT INTO table_b VALUES
  ('foo', 123, null),
  ('bar', 789, null),
  ('baz', 101, null);

I am running the following query to bring ID_number_X across to Table_B:

UPDATE table_b AS B
SET id_number_x = A.id_number_x
FROM table_a AS A
WHERE B.id_number_y = A.id_number_y

This works fine, however, there are cases when there can be multiple results i.e. id_number_y can have more than one id_number_x associated with it.

How can I put those multiple results (when they occur) into additional columns?

So the result I want from the above example tables would be this:

Table B
column_1    id_number_y     id_number_x1   id_number_x2   id_number_x3
foo            123            HT59452        HT59453        HT59454
bar            789            HT59455
baz            101            HT59456

I think there could be up to 5 id_number_x for each id_number_y, so I can happily create the extra columns needed to store these.

4
  • 1
    What exactly do you want to achieve? I think the question comes down to what purpose Table B serves? The query you need would actually be a pivot, needing crosstab functionality, but there may be a better way of doing things than saving to an unnormalized table. Commented Feb 2, 2017 at 16:03
  • Thanks for the comment dezso. Table B is simply then populated with data to be exported back to a spreadsheet.
    – Matt
    Commented Feb 2, 2017 at 16:05
  • 1
    So it could be just as well be a simple query or a view? Commented Feb 2, 2017 at 16:07
  • Yeah I guess the table doesn't actually need to be updated, it could just be a view
    – Matt
    Commented Feb 2, 2017 at 16:19

2 Answers 2

3

A few things table_b's schema must be fixed. You can't have an update that updates variable columns, some of which may not even be created. Because you don't know how many matches you'll have, what you likely want here is an array type.

ALTER TABLE table_b
  DROP COLUMN ID_number_X,
  ADD COLUMN ID_number_X text[];

Now you have an array type of text[] on the table.

      Table "pg_temp_6.table_b"
   Column    |   Type    | Modifiers 
-------------+-----------+-----------
 column_1    | text      | 
 id_number_y | integer   | 
 id_number_x | integer[] | 

And you can proceed creating UPDATE. Next, you need a simply query from which to do the update.

SELECT id_number_y, array_agg(id_number_x) AS id_number_x
FROM table_a
GROUP BY id_number_y;

 id_number_y |        id_number_x         
-------------+---------------------------
         123 | {HT59452,HT59453,HT59454}
         101 | {HT59456}
         789 | {HT59455}

With this you can wrap the query in the UPDATE and get what you want.

UPDATE table_b AS B
SET id_number_x = A.id_number_x
FROM (
    SELECT id_number_y, array_agg(id_number_x) AS id_number_x
    FROM table_a
    GROUP BY id_number_y
) AS A
WHERE B.id_number_y = A.id_number_y;

Now you have..

# TABLE TABLE_b;
 column_1 | id_number_y |        id_number_x        
----------+-------------+---------------------------
 foo      |         123 | {HT59452,HT59453,HT59454}
 bar      |         789 | {HT59455}
 baz      |         101 | {HT59456}

That said, this is rarely necessary and there are two other ways to do this which may better fit your needs,

  1. MATERIALIZED VIEW
  2. VIEW

Normally, this isn't needed because you simply use a JOIN.

0

Looks like your final query would need array_agg or string_agg https://www.postgresql.org/docs/9.5/static/functions-aggregate.html

My syntax may be off. I'm not typically in postgresql.

select
    b.column_1
    a.ID_number_Y,
    string_agg(a.ID_number_X,',')
from
    table_a a,
    table_b b
where
    a.ID_number_Y = b.ID_number_Y
group by
    b.column_1,
    a.ID_number_Y;

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.