Re: Relational question

From: John Gilson (jag_at_acm.org)
Date: 12/14/04


Date: Tue, 14 Dec 2004 05:31:04 GMT

If one considers the question as purely a SQL question then,
yes, the two queries are equivalent but with further explanation
or qualification needed, as you noted. In purely relational terms,
the qualifications are more intrinsic to the discipline. That is, all
relational queries remove redundant duplicate rows implicitly
thus obviating the need for SQL's explicit DISTINCT but, in
general, requiring its use in an equivalent SQL query. Also,
in relational queries, joining relations A and B by stating the join
condition as simply A=B is taken to mean a natural join, that is, an
equijoin with respect to all corresponding pairs of attributes of the
same name appearing in both relations. So, assuming relations
A = (attr1, attr2)
B = (attr1, attr3),
A LEFT JOIN B ON A=B as a relational algebra expression
would be transformed into SQL as
SELECT DISTINCT A.attr1, A.attr2, B.attr1, B.attr3
FROM A LEFT JOIN B ON A.attr1=B.attr1

Note that if this were an INNER JOIN we would only need to
include one copy of each pair of duplicate attributes, e.g.,
A INNER JOIN B ON A=B as a relational algebra expression
would be transformed into SQL as either
SELECT DISTINCT A.attr1, A.attr2, B.attr3
FROM A JOIN B ON A.attr1=B.attr1
or
SELECT DISTINCT B.attr1, A.attr2, B.attr3
FROM A JOIN B ON A.attr1=B.attr1

--
JAG
"Steve Kass" <skass@drew.edu> wrote in message news:%23ohSMTS4EHA.1260@TK2MSFTNGP12.phx.gbl...
> True, but doesn't this show that the answer to the original poster's
> question is "no", or at least "only under some circumstances" (In addition
> to making this relational with DISTINCT, I think the join "a.a" in the
> second join must join all columns of a with their counterparts, since
> otherwise the two original joins do not even have the same sets of
> attributes.)
>
> SK
>
> John Gilson wrote:
>
> >I think if you have each query return the same attributes and
> >ensure that the result is a relation, i.e., a set and not a bag,
> >then the results will be the same and hence the expressions
> >relationally equivalent.
> >
> >select DISTINCT A.colT1A, A.colT1B,
> >                             B.colT2A, B.colT2B,
> >                             C.colT3A, C.colT3B
> >from
> >    @t1 as a
> >    left outer join
> >    @t2 as b
> >    on a.colT1A = b.colT2A
> >    left outer join
> >    @t3 as c
> >    on a.colT1A = c.colT3A
> >
> >select DISTINCT AB.colT1A, AB.colT1B,
> >                             AB.colT2A, AB.colT2B,
> >                             AC.colT3A, AC.colT3B
> > from (
> >  select *
> >  from @t1 as a left outer join @t2 as b
> >  on a.colT1A = b.colT2A
> >) as AB inner join (
> >  select *
> >  from @t1 as a left outer join @t3 as c
> >  on a.colT1A = c.colT3A
> >) as AC
> >on AB.colT1A = AC.colT1A
> >
> >--
> >JAG
> >
> >"Steve Kass" <skass@drew.edu> wrote in message news:u0U8q8z3EHA.824@TK2MSFTNGP11.phx.gbl...
> >
> >
> >>Hm.  Then what's going on here?
> >>
> >>declare @t1 table(colT1A int, colT1B int)
> >>declare @t2 table(colT2A int, colT2B int)
> >>declare @t3 table(colT3A int, colT3B int)
> >>
> >>insert into @t1 values(1,1)
> >>insert into @t1 values(1,2)
> >>insert into @t1 values(2,3)
> >>
> >>insert into @t2 values(1,1)
> >>insert into @t2 values(3,2)
> >>
> >>insert into @t3 values(2,1)
> >>insert into @t3 values(4,2)
> >>
> >>select *
> >>from
> >>    @t1 as a
> >>    left outer join
> >>    @t2 as b
> >>    on a.colT1A = b.colT2A
> >>    left outer join
> >>    @t3 as c
> >>    on a.colT1A = c.colT3A
> >>
> >>
> >>select * from (
> >>  select *
> >>  from @t1 as a left outer join @t2 as b
> >>  on a.colT1A = b.colT2A
> >>) as AB inner join (
> >>  select *
> >>  from @t1 as a left outer join @t3 as c
> >>  on a.colT1A = c.colT3A
> >>) as AC
> >>on AB.colT1A = AC.colT1A
> >>
> >>--SK
> >>
> >>John Gilson wrote:
> >>
> >>
> >>
> >>>"Vadim Rapp" <vrapp@nospam.polyscience.com> wrote in message
> >>>news:%23H%23smvS3EHA.3388@TK2MSFTNGP15.phx.gbl...
> >>>
> >>>
> >>>
> >>>
> >>>>Hello,
> >>>>
> >>>>are the following equivalent?
> >>>>
> >>>>(A LOJ B on a=b) LOJ C on a.c
> >>>>
> >>>>and
> >>>>
> >>>>(A LOJ B on a.b) Join (A LOJ C on a.c) on a.a
> >>>>
> >>>>
> >>>>?
> >>>>
> >>>>
> >>>>thanks,
> >>>>
> >>>>Vadim Rapp
> >>>>
> >>>>
> >>>>
> >>>>
> >>>Yes, the two expressions above are relationally equivalent.  Let's see why.
> >>>
> >>>A LEFT OUTER JOIN, e.g.,
> >>>
> >>>A
> >>>LEFT OUTER JOIN
> >>>B
> >>>ON A=B
> >>>
> >>>is, loosely specified, equivalent to
> >>>
> >>>(A
> >>>INNER JOIN
> >>>B
> >>>ON A=B)
> >>>UNION
> >>>(A WHERE NOT EXISTS A=B)
> >>>
> >>>which we'll refer to as [1].
> >>>
> >>>Let's look at the first LEFT JOIN query [2]:
> >>>
> >>>A
> >>>LEFT OUTER JOIN
> >>>B
> >>>ON A=B
> >>>LEFT OUTER JOIN
> >>>C
> >>>ON A=C
> >>>
> >>>This can be transformed using [1] to
> >>>
> >>>(A
> >>>INNER JOIN
> >>>B
> >>>ON A=B
> >>>UNION
> >>>A WHERE NOT EXISTS A=B) AS AB
> >>>INNER JOIN
> >>>C
> >>>ON AB=C
> >>>
> >>>UNION
> >>>
> >>>(A
> >>>INNER JOIN
> >>>B
> >>>ON A=B
> >>>UNION
> >>>A WHERE NOT EXISTS A=B) AS AB
> >>>WHERE NOT EXISTS AB=C
> >>>
> >>>which we'll refer to as [3].
> >>>
> >>>This can then be expanded into the following four queries that are
> >>>unioned:
> >>>
> >>>A
> >>>INNER JOIN
> >>>B
> >>>ON A=B
> >>>INNER JOIN
> >>>C
> >>>ON A=C
> >>>
> >>>UNION
> >>>
> >>>(A WHERE NOT EXISTS A=B) AS A
> >>>INNER JOIN
> >>>C
> >>>ON A=C
> >>>
> >>>UNION
> >>>
> >>>(A
> >>>INNER JOIN
> >>>B
> >>>ON A=B) AS AB
> >>>WHERE NOT EXISTS AB=C
> >>>
> >>>UNION
> >>>
> >>>A WHERE NOT EXISTS A=B AND NOT EXISTS A=C
> >>>
> >>>which we'll refer to collectively as [4] and the constituent queries
> >>>in order as [4.1], [4.2], [4.3] and [4.4].
> >>>
> >>>Let's look at the second LEFT JOIN query [5]:
> >>>
> >>>(A
> >>>LEFT OUTER JOIN
> >>>B
> >>>ON A=B) AS AB
> >>>INNER JOIN
> >>>(A
> >>>LEFT OUTER JOIN
> >>>C
> >>>ON A=C) AS AC
> >>>ON AB=AC
> >>>
> >>>Using the above equivalence for LEFT JOIN, [1], we can transform this
> >>>into:
> >>>
> >>>(A
> >>>INNER JOIN
> >>>B
> >>>ON A=B
> >>>UNION
> >>>A WHERE NOT EXISTS A=B) AS AB
> >>>INNER JOIN
> >>>(A
> >>>INNER JOIN
> >>>C
> >>>ON A=C
> >>>UNION
> >>>A WHERE NOT EXISTS A=C) AS AC
> >>>ON AB=AC
> >>>
> >>>and refer to it as [6].
> >>>
> >>>Our goal will be to transform [6] into four queries that are unioned
> >>>as in query [4].  Let's assume the following:
> >>>
> >>>J = (Inner) Join operator
> >>>U = Union operator
> >>>A', B', C', D', T' are all tables
> >>>
> >>>We can see that the query [6] is of the form
> >>>
> >>>(A' U B') J (C' U D')
> >>>
> >>>It's clear that
> >>>
> >>>(A' U B') J T' = (T' J A') U (T' J B')
> >>>
> >>>If T' = (C' U D') then
> >>>
> >>>(A' U B') J (C' U D') = ((C' U D') J A') U ((C' U D') J B') =
> >>>(A' J C') U (A' J D') U (B' J C') U (B' J D')
> >>>
> >>>which we'll refer to as [7].
> >>>
> >>>So we can see that the LEFT JOIN query [5] can be transformed into [6]
> >>>and then into four queries that are unioned in [7].  Let's now
> >>>determine whether they can be transformed into the same four unioned
> >>>queries as [4].
> >>>
> >>>Let's assign A', B', C' and D' to table expressions in [6].
> >>>
> >>>A' = (A INNER JOIN B ON A=B)
> >>>B' = (A WHERE NOT EXISTS A=B)
> >>>C' = (A INNER JOIN C ON A=C)
> >>>D' = (A WHERE NOT EXISTS A=C)
> >>>
> >>>We can now look at the individual joins in [7]:
> >>>
> >>>(A' J C') = (A INNER JOIN B ON A=B) AS AB
> >>>                 INNER JOIN
> >>>                 (A INNER JOIN C ON A=C) AS AC
> >>>                 ON AB=AC
> >>>             = A
> >>>                INNER JOIN
> >>>                B
> >>>                ON A=B
> >>>                INNER JOIN
> >>>                C
> >>>                ON A=C
> >>>
> >>>which is equal to [4.1].
> >>>
> >>>(A' J D') = (A INNER JOIN B ON A=B) AS AB
> >>>                 INNER JOIN
> >>>                 (A WHERE NOT EXISTS A=C) AS A
> >>>                 ON AB=A
> >>>             = A
> >>>                INNER JOIN
> >>>                B
> >>>                ON A=B AND
> >>>                       WHERE NOT EXISTS A=C
> >>>
> >>>which is equal to [4.3].
> >>>
> >>>(B' J C') = (A WHERE NOT EXISTS A=B) AS A
> >>>                INNER JOIN
> >>>                (A INNER JOIN C ON A=C) AS AC
> >>>                ON A=AC
> >>>             = (A WHERE NOT EXISTS A=B) AS A
> >>>                INNER JOIN
> >>>                C
> >>>                ON A=C
> >>>
> >>>which is equal to [4.2].
> >>>
> >>>(B' J D') = (A WHERE NOT EXISTS A=B) AS A1
> >>>                 INNER JOIN
> >>>                 (A WHERE NOT EXISTS A=C) AS A2
> >>>                 ON A1=A2
> >>>             = A WHERE NOT EXISTS A=B AND NOT EXISTS A=C
> >>>
> >>>which is equal to [4.4].
> >>>
> >>>Therefore, [7], with the substitutions above, is equal to [4] and
> >>>hence [2] is equal to [5].
> >>>
> >>>--
> >>>JAG
> >>>
> >>>
> >>>
> >>>
> >>>
> >>>
> >
> >
> >
> >
> >


Relevant Pages

  • Re: Left Join vs Right JOIN
    ... Department details for that customer. ... INNER JOIN Customer AS c ON cd.CustomerID = c.CustomerID ... If a field in an outer JOIN is not nullable, but because of the OUTER JOIN ... Links for SQL Server Books Online: ...
    (microsoft.public.sqlserver.programming)
  • Re: appending new records to a table with a compound primary key
    ... Thanks for the additional explanation, ... That's exactly it as far as an outer join is concerned. ... With an inner ... Paul wrote: ...
    (microsoft.public.access.queries)
  • Re: Outer Join not working
    ... Evaluate FROM clause. ... Rows that don't match the ON condition are not included if it's an INNER ... where the JobID column is from the inner table of an outer join. ...
    (microsoft.public.sqlserver.programming)
  • Re: passing parameters from one query to another
    ... > Try using a function rather than a stored procedure (I assume you use MS SQL ... >>I have two queries, where each accept parameters. ... >> sending the parameters from the outer query to the inner. ...
    (microsoft.public.access.queries)
  • Re: I want to update a row if it exists and Insert if the row dont ex
    ... > I am Using Left outer join to join the tables. ... > update the info on inner table. ... confirmation of the update if it exists? ... Open a recordset on the query. ...
    (microsoft.public.access.modulesdaovba)