Обсуждение: Looking for the correct solution for a generic problem.
I've been wondering about this for quite a while now. And I suspect there is a bog-standard way that is better than the rather clumsy approach I am following now (it feels clumsy anyway). I've got table B which is linked to table A as in CREATE TABLE A ( id serial, foo text, ); CREATE TABLE B ( a_id int references A (id), id serial, bar text ); Now I want to retrieve rows from A as in SELECT DISTINCT A.foo FROM A,B WHERE A.foo [matches some criteria] OR B.bar [matches some other criteria] AND A.id = B.a_id; This works fine if there is *at least* one row in B for each row in A. If there isn't, I obviously get 0 results even if the column foo in A matches the desired criteria. But I do want the rows from A even if there is no row in B that is linked to those rows in A that match the criteria. If the column bar in B matches the desired criteria, I also want the rows in A that are linked to those rows in B. The solution I am using now is to create a 'dummy' row in B for each row in A on the application level, which I then filter out of the result sets again (B gets an extra 'dummy' column which is set to true, if applicable). I not only suspect that there is a proper way to do this, but that there is ample discussion in the relevant literature . . . if I only knew under which keyword to look it up . . . Regards, Frank
On Thu, 7 Feb 2002, Frank Joerdens wrote: > Now I want to retrieve rows from A as in > > SELECT DISTINCT A.foo > FROM A,B > WHERE A.foo [matches some criteria] > OR B.bar [matches some other criteria] > AND A.id = B.a_id; > > This works fine if there is *at least* one row in B for each row in A. > If there isn't, I obviously get 0 results even if the column foo in A > matches the desired criteria. But I do want the rows from A even if > there is no row in B that is linked to those rows in A that match the > criteria. If the column bar in B matches the desired criteria, I also > want the rows in A that are linked to those rows in B. Sounds like you want a left outer join. Maybe... select distinct a.foo from a left outer join b on (a.ID = b.a_id) where a.foo [matches] or B.bar [matches]
Frank Joerdens <frank@joerdens.de> writes: > This works fine if there is *at least* one row in B for each row in A. > If there isn't, I obviously get 0 results even if the column foo in A > matches the desired criteria. But I do want the rows from A even if > there is no row in B that is linked to those rows in A that match the > criteria. You want an "outer join". Something likeFROM A LEFT JOIN B ON (A.id = B.a_id)WHERE [other criteria] regards, tom lane
On Thu, Feb 07, 2002 at 01:31:03PM -0800, Stephan Szabo wrote: > On Thu, 7 Feb 2002, Frank Joerdens wrote: > > > Now I want to retrieve rows from A as in > > > > SELECT DISTINCT A.foo > > FROM A,B > > WHERE A.foo [matches some criteria] > > OR B.bar [matches some other criteria] > > AND A.id = B.a_id; > > > > This works fine if there is *at least* one row in B for each row in A. > > If there isn't, I obviously get 0 results even if the column foo in A > > matches the desired criteria. But I do want the rows from A even if > > there is no row in B that is linked to those rows in A that match the > > criteria. If the column bar in B matches the desired criteria, I also > > want the rows in A that are linked to those rows in B. > > Sounds like you want a left outer join. > > Maybe... > select distinct a.foo from > a left outer join b on (a.ID = b.a_id) > where a.foo [matches] or B.bar [matches] Ah! There indeed is an entire little chapter (6.6.3) in my 'Fundamentals of Database Systems' (Elmasri/Navathe) on this, and Bruce talks about it too . . . albeit saying (in my version of his book) that joins ain't supported in 7.0 and that you need to simulate 'em using UNION ALL and subqueries. The problem here was a combination of hubris and laziness on my part: I thought I didn't need to learn about join syntax because I figured it could all be done with boolean logic as in my query example above . . . Thanks! Frank
Frank Joerdens wrote: > I've been wondering about this for quite a while now. And I suspect > there is a bog-standard way that is better than the rather clumsy > approach I am following now (it feels clumsy anyway). I've got table B > which is linked to table A as in > > CREATE TABLE A ( > id serial, > foo text, > ); > > CREATE TABLE B ( > a_id int references A (id), > id serial, > bar text > ); > > Now I want to retrieve rows from A as in > > SELECT DISTINCT A.foo > FROM A,B > WHERE A.foo [matches some criteria] > OR B.bar [matches some other criteria] > AND A.id = B.a_id; > Perhaps I am clueless, but wouldn't you want to do this SELECT DISTINCT A.foo FROM A,B WHERE ((A.foo =1) OR (B.bar =2)) AND A.id = B.a_id; Actually, I think the outerjoin is right. I had problems like this in the past. I think the other posts answer it. Mark