1

First I am new to Postgres so I may be describing this problem incorrectly so please point me to an answer if it has already been answered.

I have a database with 10 columns. Lets say 4 columns all use the same codes for values (i.e the letter a, b, d, e) I want to rename all of these in the query to what they are matched with values in another table.

I have a very long approach at this stage involving a nested With statements. Is there a easy way to go from say:

table1:

id    | col1 | col2 | col3 | col4
------+------+------+------+------
Row_1 | a    | c    | d    | e
Row_2 | c    | c    | c    | c 
Row_3 | e    | d    | d    | c

Lookup Table:

code | value
-----+---------
a    | apple
b    | banana
c    | catfish
d    | dog
e    | egg

Desired result:

Row_1 | apple   | catfish | dog     | egg
Row_2 | catfish | catfish | catfish | dog
Row_3 | egg     | dog     | dog     | catfish
Erwin Brandstetter
  • 605,456
  • 145
  • 1,078
  • 1,228
Daniel
  • 13
  • 3
  • 1
    https://dba.stackexchange.com/questions/145038/how-to-join-to-the-same-table-multiple-times This looks like the approach I was after. – Daniel Sep 04 '19 at 15:09

1 Answers1

0

Yes, https://dba.stackexchange.com/questions/145038/how-to-join-to-the-same-table-multiple-times should basically work for you. But you want an UPDATE, which is a bit different:

Either way, code values in table lookup have to be UNIQUE for obvious reasons.

Updating a single column is simple:

UPDATE table1 t
SET    col1 = l.value
FROM   lookup l
WHERE  t.col1 = l.code;

If no match is found, the row it table1 is not updated. But running separate updates for every column is considerably more expensive than updating all columns at once - which is a bit more tricky:

UPDATE table1 t
SET    col1 = COALESCE(l1.value, t.col1)
     , col2 = COALESCE(l2.value, t.col2)
     , col3 = COALESCE(l3.value, t.col3)
     , col4 = COALESCE(l4.value, t.col4)
FROM   table1 t1
LEFT   JOIN lookup l1 ON t.col1 = l1.code
LEFT   JOIN lookup l2 ON t.col2 = l2.code
LEFT   JOIN lookup l3 ON t.col3 = l3.code
LEFT   JOIN lookup l4 ON t.col4 = l4.code
WHERE  t1.id = t.id;

In this case, all rows are updated. While there can be NULL values in table1 or missing values in lookup we need LEFT [OUTER] JOIN to not exclude rows from the update. So we need another instance of table1 in the FROM clause and LEFT JOIN to that.

And the added COALESCE retains the original value for each individual column where no match was found. The optimal query depends on details not disclosed in your question ...

You might add another WHERE clause to exclude rows where nothing changes. See:

Erwin Brandstetter
  • 605,456
  • 145
  • 1,078
  • 1,228