Skip to content
Advertisement

How to query for the difference between the sequences of two columns, from differing tables

I need a query that will compare the sequences of two columns (from two different tables) and display the first differing result. Summary with details follow:

  • Operating out of a PostgreSQL server and using DBeaver
  • Two tables with identical column headers.
  • One entry (creq_id) will have 36 sequences (seq).
  • When the UI modifies the data (chan_id), Table B records the new entry.
    • Modification can be a change to original value or a new addition to the sequence.
  • Query should compare each sequence (total of 36 sequences) from both tables and stop at the first difference which is recorded in Table B.

Example of changing/overwriting a chan_id:

Table A

creq_id chan_id seq
29022 400 1
29022 0 2
29022 0 3

Table B

creq_id chan_id seq
29022 500 1
29022 0 2
29022 0 3

Example of adding a new chan_id

Table A

creq_id chan_id seq
29022 400 1
29022 0 2
29022 0 3

Table B

creq_id chan_id seq
29022 400 1
29022 500 2
29022 0 3

In either case above, the result I am seeking:

  • Table A.chan_id as orig_value
  • Table B.chan_id as new_value
orig_value new_value
400 500

Advertisement

Answer

The basic query is to join each table by creq_id and seq_id, then check if their chan_ids are not equal.

To differentiate between a change and an add, if tableA’s chan_id is 0 then it’s a change and we need to use chan_id from the previous sequence. We get that with a subquery.

select
  a.creq_id,
  case a.chan_id
  when 0 then (
      -- Get the previous chan_id
      select chan_id
      from tablea
      where creq_id = a.creq_id
        and seq = a.seq - 1
  )
  else
      a.chan_id
  end as original,
  b.chan_id as new,
  a.seq,
  b.seq
from tablea a
join tableb b on a.creq_id = b.creq_id and a.seq = b.seq
where a.chan_id != b.chan_id

This causes a problem, what if you want to store a 0 then change it? It looks the same as having added a new value. To avoid this, use null instead of 0 to mean “no value”.

select
  a.creq_id,
  coalesce(
      a.chan_id,
      (
        -- Get the previous chan_id
        select chan_id
        from tablea
        where creq_id = a.creq_id
          and seq = a.seq - 1
      )
  ) as original,
  b.chan_id as new,
  a.seq,
  b.seq
from tablea a
join tableb b on a.creq_id = b.creq_id and a.seq = b.seq
-- skip when both columns are null, because null != null
where (a.chan_id is null and b.chan_id is not null)
   or a.chan_id != b.chan_id
User contributions licensed under: CC BY-SA
5 People found this is helpful
Advertisement