Thread: Re: [SQL] Beginner question - select with multiple tables

Re: [SQL] Beginner question - select with multiple tables

From
Dave Inskeep
Date:
Herouth,

Sorry if I was unclear; I think you missed my point. Of the four bodx
tables, only one contains the text 'brake' in the bodx field. There
are four instances in the vallbod1 table that contain brake.
vall_bod2, 3, and 4 do not have any records that contain 'brake' in
the bod2, bod3, or bod4 fields, respectively.

I expect the query to return the node field from the four records in
vall_bod1 that contain 'brake'. If I query over vall and vall_bod1
alone, I get the four records. If I query over vall, vall_bod1, and
vall_bod2, I get different results depending if vall_bod2 contains ANY
records, matching or not. If vall_bod2 has no records, the query
returns no records, period. If vall_bod2 contains even a single record
that does not match the query, the four expected records in vall_bod1
are returned.

My point is that the query produces different results if any of the
tables in the query contain no records. Since I'm using an OR between
the tables in my where clause, I find this strange.



---Herouth Maoz <herouth@oumail.openu.ac.il> wrote:
>
> At 6:51 +0200 on 20/1/99, Dave Inskeep wrote:
>
>
> >
> > select distinct vall.node from vall, vall_bod1, vall_bod2 where
> > ( vall.node = vall_bod1.node and vall_bod1.bod1 LIKE '%brake%' ) or
> > ( vall.node = vall_bod2.node and vall_bod2.bod2 LIKE '%brake%' );
> >
> > However, if I insert a record into vall_bod2 (whether or not it
> > contains the word brake) and a corresponding header record into vall
> > with a matching node, the same exact query will return the nodes of
> > all records in vall_bod1 with the word 'brake' in the bod1 field.
> >
> > The same holds true if I query across vall_bod1, 2, and 3, and there
> > are no records in vall_bod3. If I insert a single record in
vall_bod3,
> > even if it doesn't match, the query will work for matching records
in
> > vall_bod1 and vall_bod2. Ditto when I try across 1-4.
> >
> > Can someone explain why this happens, am I doing something wrong? Is
> > there a better way to achieve the same results, i.e. JOINS? Does
> > Postgresql support JOINS?
>
> First, you *are* doing a join here.
>
> But you are missing the logic. Perhaps you should tell us, instead
of what
> query you did (which obviously returns the correct results by your
> description), what was the result you wanted? What rows did you want
to be
> returned?
>
> Herouth
>
> --
> Herouth Maoz, Internet developer.
> Open University of Israel - Telem project
> http://telem.openu.ac.il/~herutma
>
>
>

_________________________________________________________
DO YOU YAHOO!?
Get your free @yahoo.com address at http://mail.yahoo.com


Re: [SQL] Beginner question - select with multiple tables

From
herouth maoz
Date:
On Thu, 21 Jan 1999, Dave Inskeep wrote:

> I expect the query to return the node field from the four records in
> vall_bod1 that contain 'brake'. If I query over vall and vall_bod1
> alone, I get the four records. If I query over vall, vall_bod1, and
> vall_bod2, I get different results depending if vall_bod2 contains ANY
> records, matching or not. If vall_bod2 has no records, the query
> returns no records, period. If vall_bod2 contains even a single record
> that does not match the query, the four expected records in vall_bod1
> are returned.
>
> My point is that the query produces different results if any of the
> tables in the query contain no records. Since I'm using an OR between
> the tables in my where clause, I find this strange.
>

OK. This is the expected behavior, but let me explain why.

When you do a join, you are actually doing a cartezian product of the
three tables. That is, in theory, each record from vall is matched against
each record from vall_bod1, and with each row from vall_bod2.

This means that initially, before the "where" part rejects unwanted
combinations of rows, you get a very large set of combined rows. Suppose
vall has N records, vall_bod1 has M1 records and vall_bod2 has M2 records,
the initial set of rows from which your required rows is selected contains
N*M1*M2 combined rows.

Follow so far? These are the candidate rows, and they are filtered out
according to your where clause.

But here is the rub: if one of the tables is empty, say vall_bod2, then M2
is zero, right? So, your where clause is applied to a set containing
N*M1*0 records, that is, to an empty set.

Ah... Nothing from nothing gives nothing.

So, as was suggested here, you need to use a union rather than a join.

Herouth