How to merge (upsert & delete orphan rows) to tableA?  
tableA:
+---------+--------+----------+-------+
| company | option | category | rates |
+---------+--------+----------+-------+
| a       | f      | null     | 2.5   |
+---------+--------+----------+-------+
| a       | f      | d        | 2     | *
+---------+--------+----------+-------+
| a       | g      | e        | 3     | **
+---------+--------+----------+-------+
| c       | g      | e        | 4     |
+---------+--------+----------+-------+
| d       | f      | d        | 1     |
+---------+--------+----------+-------+
* denotes orphan row*.
** denotes value to change (3 -> 4).
Only touch companies existing in tableB (a & c in the example, leave d alone).
tableB:
+---------+--------+----------+-------+
| company | option | category | rates |
+---------+--------+----------+-------+
| a       | f      | null     | 2.5   |
+---------+--------+----------+-------+
| a       | g      | e        | 4     |
+---------+--------+----------+-------+
| c       | g      | e        | 4     |
+---------+--------+----------+-------+
There is a unique index on (company, option, category) in both tables.  
Desired resulting tableA:
+---------+--------+----------+-------+
| company | option | category | rates |
+---------+--------+----------+-------+
| a       | f      | null     | 2.5   |
+---------+--------+----------+-------+
| a       | g      | e        | 4     | <-
+---------+--------+----------+-------+
| c       | g      | e        | 4     |
+---------+--------+----------+-------+
| d       | f      | d        | 1     |
+---------+--------+----------+-------+
Only the second row (a,f,d,2) was deleted and rates was changed from 3 to  4 for (a,g,e).
Here is a fiddle: https://rextester.com/QUVC30763
I'm thinking to first delete the orphan row with this:
DELETE from tableA
 USING tableB
 WHERE 
   -- ignore rows with IDs that don't exist in tableB
   tableA.company = tableB.company
   -- ignore rows that have an exact all-column match in tableB
   AND NOT EXISTS 
      (select * from tableB 
      where tableB.company is not distinct from tableA.company 
      AND tableB.option is not distinct from tableA.option 
      AND tableB.category is not distinct from tableA.category );
Then upsert with this:
 INSERT INTO tableA (company, option, category, rates) 
   SELECT company, option, category, rates
   FROM   tableB
 ON CONFLICT (company, option, category) 
 DO update
   set rates= EXCLUDED.rates
 WHERE 
      tableA.rates IS DISTINCT FROM 
      EXCLUDED.rates;
But the problem with the upsert function is that it can't handle nullable fields. I have to set -1 in place of null or else the function won't be able to know if there are duplicates or not. I feel like setting -1 in place of null will create many workarounds in the future, so I'd like to avoid that if I can.
Note: I found that INSERT ... ON CONFLICT ... DO UPDATE is probably the way to go:
But I haven't seen a query suitable for my case. And I'm not sure if it's possible with nullable fields. Hence the question:
Is there a clean way to merge with nullable fields?
 
    