Re: Limitting full join to one match - Mailing list pgsql-general

From John W Higgins
Subject Re: Limitting full join to one match
Date
Msg-id CAPhAwGw2n4ZNRL6DNaYV0wgRiidp6LW-dj_GVAxaCJK_JB2Q6A@mail.gmail.com
Whole thread Raw
In response to Limitting full join to one match  ("Phil Endecott" <spam_from_pgsql_lists@chezphil.org>)
Responses Re: Limitting full join to one match  ("Phil Endecott" <spam_from_pgsql_lists@chezphil.org>)
List pgsql-general


On Wed, Dec 5, 2018 at 4:34 PM Phil Endecott <spam_from_pgsql_lists@chezphil.org> wrote:
Dear Experts,

I have a couple of tables that I want to reconcile, finding rows
that match and places where rows are missing from one table or the
other:

...
 
So my question is: how can I modify my query to output only two rows,
like this:?

+------------+--------+------------+--------+
|    date    | amount |    date    | amount |
+------------+--------+------------+--------+
| 2018-01-01 |  10.00 | 2018-01-01 |  10.00 |
| 2018-02-01 |   5.00 |            |        |
|            |        | 2018-03-01 |   8.00 |
| 2018-04-01 |   5.00 | 2018-04-01 |   5.00 |
| 2018-05-01 |  20.00 | 2018-05-01 |  20.00 |  1
| 2018-05-01 |  20.00 | 2018-05-01 |  20.00 |  2
+------------+--------+------------+--------+


Evening Phil,

Window functions are your friend here. I prefer views for this stuff - but subqueries would work just fine.

create view a_rows as (select *, 
                       row_number() OVER (PARTITION BY date, amount) AS pos from a);
create view b_rows as (select *, 
                       row_number() OVER (PARTITION BY date, amount) AS pos from b);

select 
  a_rows.date, 
  a_rows.amount, 
  a_rows.pos,
  b_rows.date, 
  b_rows.amount,
  b_rows.pos
from 
  a_rows full join b_rows using (date,amount,pos);


John 

Any suggestions anyone?


The best I have found so far is something involving EXCEPT ALL:

db=> select * from a except all select * from b;
db=> select * from b except all select * from a;

That's not ideal, though, as what I ultimately want is something
that lists everything with its status:

+------------+--------+--------+
|    date    | amount | status |
+------------+--------+--------+
| 2018-01-01 |  10.00 |   OK   |
| 2018-02-01 |   5.00 | a_only |
| 2018-03-01 |   8.00 | b_only |
| 2018-04-01 |   5.00 |   OK   |
| 2018-05-01 |  20.00 |   OK   |
| 2018-05-01 |  20.00 |   OK   |
+------------+--------+--------+

That would be easy enough to achieve from the JOIN.


Thanks, Phil.



pgsql-general by date:

Previous
From: "Phil Endecott"
Date:
Subject: Limitting full join to one match
Next
From: Ron
Date:
Subject: Re: Limitting full join to one match