Re: Problem with left join when moving a column to another table - Mailing list pgsql-general

From Jason Long
Subject Re: Problem with left join when moving a column to another table
Date
Msg-id 1371769019.15253.50.camel@localhost.localdomain
Whole thread Raw
In response to Re: Problem with left join when moving a column to another table  (David Johnston <polobo@yahoo.com>)
Responses Re: Problem with left join when moving a column to another table  (David Johnston <polobo@yahoo.com>)
List pgsql-general
On Thu, 2013-06-20 at 15:37 -0700, David Johnston wrote:
Jason Long-2 wrote
> David,
> 
> Thank you very much for your response.
> Below is a script that will reproduce the problem with comments
> included.
> 
> ....
> 
> /*
> This is the new query that is not working correctly.  
> I am trying to left join the base table by its id and area_id.  
> I need a left join because there is no guarantee that there is a
> matching price.

The query I am pretty sure you want is:

WITH item (i_id, size_id, area_id) AS (
VALUES (1,1,10),(2,4,1),(3,19,1)
)
, price_orig (p_id, size_id, area_id) AS (
VALUES
(162,4,6),(161,4,2),(159,4,1),(638,19,9),(633,19,14),(675,19,45),(64,19,1)
)
, simple_base (p_id, area_id) AS ( SELECT p_id, area_id FROm price_orig
)
--SELECT * FROM item LEFT JOIN price_orig USING (size_id, area_id)
--original
/*  your problem query
SELECT * FROM item 
LEFT JOIN price_orig USING (size_id)
LEFT JOIN simple_base ON (price_orig.p_id = simple_base.p_id AND
item.area_id = simple_base.area_id)
*/

-- the correct query
SELECT * FROM item 
LEFT JOIN (SELECT p_id, price_orig.size_id, simple_base.area_id FROM
price_orig JOIN simple_base USING (p_id)) rebuild    USING (size_id, area_id)

In the original query you used both size and area to link to the price
table.  Even though you have moved the area to a different table in order to
keep the same semantics you have to continue performing the same relational
join.  If you intend something different then you are not providing enough
information since neither size_id nor area_id are unique within the price
table.  Because the combination of the two just happens to not be duplicated
in the supplied data the correct queries only return a single result per
item.
There is a unique constraint on the real price table.  I hadn't thought of how I will enforce the constraint across two tables.
size_id and area_id will have to be unique across both t_price_base_table and t_price_original_with_area_id.  I will want to drop area_id from t_price_original_with_area_id.

What is the best way to implement the cross table unique constraint?


In the "correct" query I am providing I am first re-joining (with an inner
join) the two tables so that they appear just like the original table
appeared.  Then I am joining the "view" to the items table using both size
and area.

The fundamental problem is that you really do not want right-hand tables in
left joins to refer to each other.

FROM item 
LEFT JOIN price_orig ON item = price_orig
LEFT JOIN price_base ON item = price_base    AND price_orig = price_base --<
the second AND expression is the problem.

I do not even try to remember nesting rules for JOIN generally.  My basic
form is:

FROM
INNER*
LEFT* (with the ON clause only referring to tables joined via INNER)

if my solution requires a different usage I either move parts of the query
into CTEs or I start explicitly adding parenthesis to explicitly group the
different pieces - and adding INNER JOIN where necessary like I did for your
example.

David J.





--
View this message in context: http://postgresql.1045698.n5.nabble.com/Problem-with-left-join-when-moving-a-column-to-another-table-tp5760187p5760210.html
Sent from the PostgreSQL - general mailing list archive at Nabble.com.



pgsql-general by date:

Previous
From: David Johnston
Date:
Subject: Re: Problem with left join when moving a column to another table
Next
From: David Johnston
Date:
Subject: Re: Easiest way to compare the results of two queries row by row and column by column