Thread: Should be easy enough to get this result (or is it possible?)...
I think the following code explains my problem more elegantly than I could ever hope to try and explain in a reasonable amount of words. The upshot of things being that I want the 2nd query below (f.foo = 'b') to return foo_id and foo. Am I missing something? My head stands poised to get clobbered with the clue-bat. Here's the test case: CREATE TABLE foo ( foo_id SERIAL NOT NULL, foo VARCHAR(32) NOT NULL ); CREATE TABLE bar ( bar_id SERIAL NOT NULL, foo_id INT NOT NULL, bar VARCHAR(32) NOT NULL); INSERT INTO foo (foo) VALUES ('a'); INSERT INTO foo (foo) VALUES ('b'); INSERT INTO foo (foo) VALUES ('c'); INSERT INTO bar (foo_id, bar) VALUES ('1','x'); INSERT INTO bar (foo_id, bar) VALUES ('1','y'); INSERT INTO bar (foo_id, bar) VALUES ('1','z'); INSERT INTO bar (foo_id, bar) VALUES ('2','x'); INSERT INTO bar (foo_id, bar) VALUES ('2','z'); SELECT f.foo_id, f.foo, b.bar_id, b.bar FROM foo AS f LEFT JOIN bar AS b on (f.foo_id = b.foo_id) WHERE (b.bar ISNULL OR b.bar = 'y') AND f.foo = 'a'; foo_id | foo | bar_id | bar --------+-----+--------+----- 1 | a | 2 | y (1 row) SELECT f.foo_id, f.foo, b.bar_id, b.bar FROM foo AS f LEFT JOIN bar AS b on (f.foo_id = b.foo_id) WHERE (b.bar ISNULL OR b.bar = 'y') AND f.foo = 'b'; foo_id | foo | bar_id | bar --------+-----+--------+----- (0 rows) SELECT f.foo_id, f.foo, b.bar_id, b.bar FROM foo AS f LEFT JOIN bar AS b on (f.foo_id = b.foo_id) WHERE (b.bar ISNULL OR b.bar = 'y') AND f.foo = 'c'; foo_id | foo | bar_id | bar --------+-----+--------+----- 3 | c | | (1 row) Any help/ideas/suggestions? -sc -- Sean Chittenden
Attachment
Sean Chittenden <sean@chittenden.org> writes: > The upshot of things being that I want the 2nd query below (f.foo =3D > 'b') to return foo_id and foo. Am I missing something? I'm not real clear on what you're after, but the query results look correct. The LEFT JOIN result (without any WHERE restriction) is test=# SELECT f.foo_id, f.foo, b.bar_id, b.bar test-# FROM foo AS f LEFT JOIN bar AS b on (f.foo_id = b.foo_id); foo_id | foo | bar_id | bar --------+-----+--------+----- 1 | a | 2 | y 1 | a | 1 | x 1 | a | 3 | z 2 | b | 4 | x 2 | b | 5 | z 3 | c | | (6 rows) and so the restricted outputs with the WHERE clauses look right. What were you trying to do exactly? regards, tom lane
On Wed, 15 May 2002, Sean Chittenden wrote: > I think the following code explains my problem more elegantly than I > could ever hope to try and explain in a reasonable amount of words. > The upshot of things being that I want the 2nd query below (f.foo = > 'b') to return foo_id and foo. Am I missing something? My head > stands poised to get clobbered with the clue-bat. Here's the test > case: > > CREATE TABLE foo ( foo_id SERIAL NOT NULL, foo VARCHAR(32) NOT NULL ); > CREATE TABLE bar ( bar_id SERIAL NOT NULL, foo_id INT NOT NULL, bar VARCHAR(32) NOT NULL); > INSERT INTO foo (foo) VALUES ('a'); > INSERT INTO foo (foo) VALUES ('b'); > INSERT INTO foo (foo) VALUES ('c'); > INSERT INTO bar (foo_id, bar) VALUES ('1','x'); > INSERT INTO bar (foo_id, bar) VALUES ('1','y'); > INSERT INTO bar (foo_id, bar) VALUES ('1','z'); > INSERT INTO bar (foo_id, bar) VALUES ('2','x'); > INSERT INTO bar (foo_id, bar) VALUES ('2','z'); > > SELECT f.foo_id, f.foo, b.bar_id, b.bar > FROM foo AS f LEFT JOIN bar AS b on (f.foo_id = b.foo_id) > WHERE (b.bar ISNULL OR b.bar = 'y') AND f.foo = 'b'; > foo_id | foo | bar_id | bar > --------+-----+--------+----- > (0 rows) I think you want something like (not completely tested): SELECT f.foo_id, f.foo, b.bar_id, b.bar from foo as f left join (select * from bar b where b.bar='y' or b.bar is null) as b on (f.foo_id=b.foo_id) where f.foo='b'; You want to limit the bar rows you're left joining to, not the rows from the output of the join I think.
> > I think the following code explains my problem more elegantly than I > > could ever hope to try and explain in a reasonable amount of words. > > The upshot of things being that I want the 2nd query below (f.foo = > > 'b') to return foo_id and foo. Am I missing something? My head > > stands poised to get clobbered with the clue-bat. Here's the test > > case: > > > > CREATE TABLE foo ( foo_id SERIAL NOT NULL, foo VARCHAR(32) NOT NULL ); > > CREATE TABLE bar ( bar_id SERIAL NOT NULL, foo_id INT NOT NULL, bar VARCHAR(32) NOT NULL); > > INSERT INTO foo (foo) VALUES ('a'); > > INSERT INTO foo (foo) VALUES ('b'); > > INSERT INTO foo (foo) VALUES ('c'); > > INSERT INTO bar (foo_id, bar) VALUES ('1','x'); > > INSERT INTO bar (foo_id, bar) VALUES ('1','y'); > > INSERT INTO bar (foo_id, bar) VALUES ('1','z'); > > INSERT INTO bar (foo_id, bar) VALUES ('2','x'); > > INSERT INTO bar (foo_id, bar) VALUES ('2','z'); > > > > SELECT f.foo_id, f.foo, b.bar_id, b.bar > > FROM foo AS f LEFT JOIN bar AS b on (f.foo_id = b.foo_id) > > WHERE (b.bar ISNULL OR b.bar = 'y') AND f.foo = 'b'; > > foo_id | foo | bar_id | bar > > --------+-----+--------+----- > > (0 rows) > > I think you want something like (not completely tested): > SELECT f.foo_id, f.foo, b.bar_id, b.bar > from foo as f left join > (select * from bar b where b.bar='y' or b.bar is null) as b > on (f.foo_id=b.foo_id) where f.foo='b'; > > You want to limit the bar rows you're left joining to, not > the rows from the output of the join I think. Cha-ching! Yeah, you successfully clubbed me w/ the clue-bat: left join on a sub-select gave me exactly what I wanted: thank you. -sc -- Sean Chittenden