Home All Groups Group Topic Archive Search About

How to SELECT data among 4 tables?

Author
26 Jan 2006 11:30 PM
Abel Chan
Hi there,

I have 4 tables:
Summary_Table
Header_Table
Detail_Table_1
Detail_Table_2

Summary_TableID is defined on both Summary_Table and Header_Table. 
Summary_Table is like a parent table to Header_Table.

Header_TableID is defined on Header_Table, Detail_Table_1 and
Detail_Table_2.  Header_Table is like a parent to Detail_Table_1 and
Detail_Table_2.

What I try to do is to retrieve records from all 4 tables.  First I join
Summary_Table and Header_Table together by using the Summary_TableID on both
tables.  If it returns record, I will join the returned Header_Table’s
Header_TableID to both Detail_Table_1 and Detail_Table_2’s Header_TableID. 
Joining Header_Table to Detail_Table_1 and Detail_Table_2 might or might not
return any record.  If it does, the select statement will contain all four
table info.  If not, it will only contain Summary_Table and Header_Table
info.   Detail_Table_1 and Detail_Table_2 fields will returns NULL.

I tried to use Left Outer Join and DISTINCT keyword below but it doesn’t
give me the correct result.  Could you help?  Thanks.


    SELECT distinct
        Summary_Table.FIELD1,
        Summary_Table.FIELD2,
Header_Table.FIELD1,
        Header_Table.FIELD2,
        Detail_Table_1.FIELD1,
Detail_Table_1.FIELD2,
        Detail_Table_2.FIELD1,
Detail_Table_2.FIELD2,
    FROM
        Summary_Table
        WITH (NOLOCK)
    JOIN Header_Table
        on    Summary_Table.Summary_TableID = Header_Table. Summary_TableID
    LEFT OUTER JOIN Detail_Table_1
        ON    Header_Table.Header_TableID = Detail_Table_1. Header_TableID
    LEFT OUTER JOIN Detail_Table_2
        ON    Header_Table.Header_TableID = Detail_Table_2. Header_TableID
WHERE
            Summary_Table.MYDATE BETWEEN @vchStartDate AND @vchEndDate

Thanks.

Abel Chan

Author
27 Jan 2006 1:29 AM
Louis Davidson
Well, other than the NOLOCK only applying to one of the tables, and having 2
detail tables,I don't see any problem with the query.  What is wrong with
the result?  I can guess it has to do with the use of distinct, but more
details are necessary.

--
----------------------------------------------------------------------------
Louis Davidson - http://spaces.msn.com/members/drsql/
SQL Server MVP
"Arguments are to be avoided: they are always vulgar and often convincing."
(Oscar Wilde)

Show quote
"Abel Chan" <awong@newsgroup.nospam> wrote in message
news:744A6350-919F-483B-911A-C8252A3A812E@microsoft.com...
> Hi there,
>
> I have 4 tables:
> Summary_Table
> Header_Table
> Detail_Table_1
> Detail_Table_2
>
> Summary_TableID is defined on both Summary_Table and Header_Table.
> Summary_Table is like a parent table to Header_Table.
>
> Header_TableID is defined on Header_Table, Detail_Table_1 and
> Detail_Table_2.  Header_Table is like a parent to Detail_Table_1 and
> Detail_Table_2.
>
> What I try to do is to retrieve records from all 4 tables.  First I join
> Summary_Table and Header_Table together by using the Summary_TableID on
> both
> tables.  If it returns record, I will join the returned Header_Table's
> Header_TableID to both Detail_Table_1 and Detail_Table_2's Header_TableID.
> Joining Header_Table to Detail_Table_1 and Detail_Table_2 might or might
> not
> return any record.  If it does, the select statement will contain all four
> table info.  If not, it will only contain Summary_Table and Header_Table
> info.   Detail_Table_1 and Detail_Table_2 fields will returns NULL.
>
> I tried to use Left Outer Join and DISTINCT keyword below but it doesn't
> give me the correct result.  Could you help?  Thanks.
>
>
> SELECT distinct
> Summary_Table.FIELD1,
> Summary_Table.FIELD2,
> Header_Table.FIELD1,
> Header_Table.FIELD2,
> Detail_Table_1.FIELD1,
> Detail_Table_1.FIELD2,
> Detail_Table_2.FIELD1,
> Detail_Table_2.FIELD2,
> FROM
> Summary_Table
> WITH (NOLOCK)
> JOIN Header_Table
> on Summary_Table.Summary_TableID = Header_Table. Summary_TableID
> LEFT OUTER JOIN Detail_Table_1
> ON Header_Table.Header_TableID = Detail_Table_1. Header_TableID
> LEFT OUTER JOIN Detail_Table_2
> ON Header_Table.Header_TableID = Detail_Table_2. Header_TableID
> WHERE
> Summary_Table.MYDATE BETWEEN @vchStartDate AND @vchEndDate
>
> Thanks.
>
> Abel Chan
>
>
Author
27 Jan 2006 1:32 AM
Adam Cox
Hi Abel.  You may want to rethink your naming convention.  It can get quite
confusing to use 'table' in name of object referencing a table.  You end up
saying "The foriegn key of the Customers_table table, is related to the
Orders_table table".  It is usually understood that an object is a table
because it is under the Tables folder in Enterprise Manager.  I would also
suggest referencing some books on the subject of "data analysis and design"
for best practices.

Using ficticious scenario, allow me to outline example that may clear things
up a little...

Customers
    PKId (primary key)
    Name
Orders
    PKId (pk)
    Name
    OrderDate
CustomerOrders
    PKId (pk)
    CustomerId (foriegn key - relative to Customers.PKId)
    OrderId (fk - relative to Orders.PKId)

Now to select all orders a specific customer has and use their name as a
criteria, the following select...

select c.Name, o.Name, o.OrderDate
from c Customers, o Orders, co CustomerOrders
where c.Name = "John"
and c.PKId *= o.PKId

The Customers and Orders tables are known as primary tables.  The
CustomerOrders table is a relationship table.  Notice all the tables have a
primary key named PKId.  They don't include any part of the table name in
the field name because they will be reference by the table name.  For
example, Customers.PKId can be assumed this is the primary key of the
Customers table.  However, notice when referencing the PKId of a table in
another (called a foriegn key), we use the table name.  For example, in
making the relationship between the Customers and Orders in the
CustomerOrders table, we call the PKId of the Customers table 'CustomerId'.

To become proficient in database design, one should reference materials
related to systems/database analysis and design.

Good luck!

Adam


Show quote
"Abel Chan" <awong@newsgroup.nospam> wrote in message
news:744A6350-919F-483B-911A-C8252A3A812E@microsoft.com...
> Hi there,
>
> I have 4 tables:
> Summary_Table
> Header_Table
> Detail_Table_1
> Detail_Table_2
>
> Summary_TableID is defined on both Summary_Table and Header_Table.
> Summary_Table is like a parent table to Header_Table.
>
> Header_TableID is defined on Header_Table, Detail_Table_1 and
> Detail_Table_2.  Header_Table is like a parent to Detail_Table_1 and
> Detail_Table_2.
>
> What I try to do is to retrieve records from all 4 tables.  First I join
> Summary_Table and Header_Table together by using the Summary_TableID on
both
> tables.  If it returns record, I will join the returned Header_Table's
> Header_TableID to both Detail_Table_1 and Detail_Table_2's Header_TableID.
> Joining Header_Table to Detail_Table_1 and Detail_Table_2 might or might
not
> return any record.  If it does, the select statement will contain all four
> table info.  If not, it will only contain Summary_Table and Header_Table
> info.   Detail_Table_1 and Detail_Table_2 fields will returns NULL.
>
> I tried to use Left Outer Join and DISTINCT keyword below but it doesn't
> give me the correct result.  Could you help?  Thanks.
>
>
> SELECT distinct
> Summary_Table.FIELD1,
> Summary_Table.FIELD2,
> Header_Table.FIELD1,
> Header_Table.FIELD2,
> Detail_Table_1.FIELD1,
> Detail_Table_1.FIELD2,
> Detail_Table_2.FIELD1,
> Detail_Table_2.FIELD2,
> FROM
> Summary_Table
> WITH (NOLOCK)
> JOIN Header_Table
> on Summary_Table.Summary_TableID = Header_Table. Summary_TableID
> LEFT OUTER JOIN Detail_Table_1
> ON Header_Table.Header_TableID = Detail_Table_1. Header_TableID
> LEFT OUTER JOIN Detail_Table_2
> ON Header_Table.Header_TableID = Detail_Table_2. Header_TableID
> WHERE
> Summary_Table.MYDATE BETWEEN @vchStartDate AND @vchEndDate
>
> Thanks.
>
> Abel Chan
>
>
Author
27 Jan 2006 7:05 AM
Abel Chan
Hi Adam,

Thanks for your suggestion.  I will look up subject of data analysis and
design
for best practices.

Abel

Show quote
"Adam  Cox" wrote:

> Hi Abel.  You may want to rethink your naming convention.  It can get quite
> confusing to use 'table' in name of object referencing a table.  You end up
> saying "The foriegn key of the Customers_table table, is related to the
> Orders_table table".  It is usually understood that an object is a table
> because it is under the Tables folder in Enterprise Manager.  I would also
> suggest referencing some books on the subject of "data analysis and design"
> for best practices.
>
> Using ficticious scenario, allow me to outline example that may clear things
> up a little...
>
> Customers
>     PKId (primary key)
>     Name
> Orders
>     PKId (pk)
>     Name
>     OrderDate
> CustomerOrders
>     PKId (pk)
>     CustomerId (foriegn key - relative to Customers.PKId)
>     OrderId (fk - relative to Orders.PKId)
>
> Now to select all orders a specific customer has and use their name as a
> criteria, the following select...
>
> select c.Name, o.Name, o.OrderDate
> from c Customers, o Orders, co CustomerOrders
> where c.Name = "John"
> and c.PKId *= o.PKId
>
> The Customers and Orders tables are known as primary tables.  The
> CustomerOrders table is a relationship table.  Notice all the tables have a
> primary key named PKId.  They don't include any part of the table name in
> the field name because they will be reference by the table name.  For
> example, Customers.PKId can be assumed this is the primary key of the
> Customers table.  However, notice when referencing the PKId of a table in
> another (called a foriegn key), we use the table name.  For example, in
> making the relationship between the Customers and Orders in the
> CustomerOrders table, we call the PKId of the Customers table 'CustomerId'.
>
> To become proficient in database design, one should reference materials
> related to systems/database analysis and design.
>
> Good luck!
>
> Adam
>
>
> "Abel Chan" <awong@newsgroup.nospam> wrote in message
> news:744A6350-919F-483B-911A-C8252A3A812E@microsoft.com...
> > Hi there,
> >
> > I have 4 tables:
> > Summary_Table
> > Header_Table
> > Detail_Table_1
> > Detail_Table_2
> >
> > Summary_TableID is defined on both Summary_Table and Header_Table.
> > Summary_Table is like a parent table to Header_Table.
> >
> > Header_TableID is defined on Header_Table, Detail_Table_1 and
> > Detail_Table_2.  Header_Table is like a parent to Detail_Table_1 and
> > Detail_Table_2.
> >
> > What I try to do is to retrieve records from all 4 tables.  First I join
> > Summary_Table and Header_Table together by using the Summary_TableID on
> both
> > tables.  If it returns record, I will join the returned Header_Table's
> > Header_TableID to both Detail_Table_1 and Detail_Table_2's Header_TableID.
> > Joining Header_Table to Detail_Table_1 and Detail_Table_2 might or might
> not
> > return any record.  If it does, the select statement will contain all four
> > table info.  If not, it will only contain Summary_Table and Header_Table
> > info.   Detail_Table_1 and Detail_Table_2 fields will returns NULL.
> >
> > I tried to use Left Outer Join and DISTINCT keyword below but it doesn't
> > give me the correct result.  Could you help?  Thanks.
> >
> >
> > SELECT distinct
> > Summary_Table.FIELD1,
> > Summary_Table.FIELD2,
> > Header_Table.FIELD1,
> > Header_Table.FIELD2,
> > Detail_Table_1.FIELD1,
> > Detail_Table_1.FIELD2,
> > Detail_Table_2.FIELD1,
> > Detail_Table_2.FIELD2,
> > FROM
> > Summary_Table
> > WITH (NOLOCK)
> > JOIN Header_Table
> > on Summary_Table.Summary_TableID = Header_Table. Summary_TableID
> > LEFT OUTER JOIN Detail_Table_1
> > ON Header_Table.Header_TableID = Detail_Table_1. Header_TableID
> > LEFT OUTER JOIN Detail_Table_2
> > ON Header_Table.Header_TableID = Detail_Table_2. Header_TableID
> > WHERE
> > Summary_Table.MYDATE BETWEEN @vchStartDate AND @vchEndDate
> >
> > Thanks.
> >
> > Abel Chan
> >
> >
>
>
>
Author
27 Jan 2006 4:05 AM
--CELKO--
Please post DDL, so that people do not have to guess what the keys,
constraints, Declarative Referential Integrity, data types, etc. in
your schema are. Sample data is also a good idea, along with clear
specifications.  It is very hard to debug code when you do not let us
see it.

Next, please read any basic RDBMS book so you will stop confusing rows
and records, fields and columns, and using that silly redundant "table"
in table names (SQL only has one data structure).   And I hope that
"@vchStartDate" is temporal and not a VARCHAR(n).

Look up what "attribute splitting" is so you will stop doing it.  I
assume that is why you the absurd "Detail_Table_1" and "Detail_Table_2"
as if you were working with arrays.

Look up why we do not mix data and metadata in a schema,

Then if the Summary table is actually a summary, why are you storing
computed data?  Is this a Data Warehouse or what?
Author
27 Jan 2006 6:38 AM
Wei-Dong XU [MS]
Hi,

For your scenario, currenlty I'd suggest please write this as one stored
procedure and then we could firstly get the query result from  Header_Table
and Summary_Table; then perform the follow-up operations according to your
design. For example:

declare @result int
select @result=count(1)
FROM
    WITH (NOLOCK)
    JOIN Header_Table
        on    Summary_Table.Summary_TableID = Header_Table. Summary_TableID

if 0 = @result
    -- we get no result from this query
else
               -- we have the value, join more tables


If you have any further question, please feel free to let us know! Enjoy a
nice weekend!

Best Regards,
Wei-Dong XU
Microsoft Support
---------------------------------------------------------------------------
This posting is provided "AS IS" with no warranties, and confers no rights.
---------------------------------------------------------------------------
It is my pleasure to be of any assistance.
Author
27 Jan 2006 4:15 PM
Louis Davidson
Explain?  I don't see that this helps?      I mean if you don't get any data
from the first join, this means that ther are no rows at all in the child
table.  Plus, this would be far faster written as an exists:

If exists (select *
              FROM Summary_Table WITH (NOLOCK) --this is still kind of
strange
                    JOIN Header_Table
                            on Summary_Table.Summary_TableID = Header_Table.
Summary_TableID)
         -- we have the value, join more tables
else
         -- we get no result from this query

The problem is, without knowledge of the exact issue (which we can find out
if Abel would give us some data.)  His query seemed ok to me, which really
says that there is possibly something wrong in the data.

--
----------------------------------------------------------------------------
Louis Davidson - http://spaces.msn.com/members/drsql/
SQL Server MVP
"Arguments are to be avoided: they are always vulgar and often convincing."
(Oscar Wilde)

Show quote
"Wei-Dong XU [MS]" <v-w***@online.microsoft.com> wrote in message
news:lsIodxwIGHA.1236@TK2MSFTNGXA02.phx.gbl...
>
> Hi,
>
> For your scenario, currenlty I'd suggest please write this as one stored
> procedure and then we could firstly get the query result from
> Header_Table
> and Summary_Table; then perform the follow-up operations according to your
> design. For example:
>
> declare @result int
> select @result=count(1)
> FROM
> WITH (NOLOCK)
> JOIN Header_Table
> on Summary_Table.Summary_TableID = Header_Table. Summary_TableID
>
> if 0 = @result
> -- we get no result from this query
> else
>               -- we have the value, join more tables
>
>
> If you have any further question, please feel free to let us know! Enjoy a
> nice weekend!
>
> Best Regards,
> Wei-Dong XU
> Microsoft Support
> ---------------------------------------------------------------------------
> This posting is provided "AS IS" with no warranties, and confers no
> rights.
> ---------------------------------------------------------------------------
> It is my pleasure to be of any assistance.
>
>
Author
27 Jan 2006 9:03 PM
Abel Chan
Hi all,

To clarify the issue, I provided an extract of the actual code.  Forgive me
all (and Adam).  I should follow the best practice next time.

Header Table:

CREATE TABLE dbo.tbOrderHeader (
    intHeaderId        int IDENTITY (1, 1)         NOT NULL
    ,dtmInsertDate     datetime             NOT NULL
    ,dtmUpdateDate     datetime             NOT NULL
    ,tiRecordStatus     tinyint             NOT NULL
)

Detail Table:

CREATE TABLE dbo.tbOrderDetail (
    intDetailId        int IDENTITY (1, 1)         NOT NULL
    ,intHeaderId               int                NOT NULL
    ,dtmInsertDate     datetime             NOT NULL
    ,dtmUpdateDate     datetime             NOT NULL
    ,tiRecordStatus     tinyint                 NOT NULL
)

Adjustment Table:

CREATE TABLE dbo.tbAdjustment(
    intAdjustmentId    int IDENTITY (1, 1)         NOT NULL
    ,intDetailId                   int                NOT NULL
    ,dtmInsertDate     datetime             NOT NULL
    ,dtmUpdateDate     datetime             NOT NULL
    ,tiRecordStatus     tinyint             NOT NULL
)

Validation Table:

CREATE TABLE dbo.tbValidation(
    intValidationId    int IDENTITY (1, 1)         NOT NULL
    ,intDetailId                   int                NOT NULL
    ,dtmInsertDate     datetime             NOT NULL
    ,dtmUpdateDate     datetime             NOT NULL
    ,tiRecordStatus     tinyint             NOT NULL
)

If joining Header and Detail returns some records, I need to find out
whether there is any record under Adjustment and Validation.  There could be
multiple records of Adjustment and validation under each detail record.

When I think more carefully, I understand why my select statement won’t
work.  This is because there is no direct relationship between Adjustment and
Validation.  They are just like separate child under the Detail table.  By
using a single SELECT statement to return Header, Detail, Adjustment and
Validation, the number of returning records will be:

(# of records Joining Header and Detail) * Adjustment * Validation.

That is exactly what happened.  I just need to create three separate SELECT
statements to handle all the information. 

Thanks again.

Abel
Author
30 Jan 2006 4:51 AM
Louis Davidson
That does make more sense.

> To clarify the issue, I provided an extract of the actual code.  Forgive
> me
> all (and Adam).  I should follow the best practice next time.

No worries at all.  It is hard to really put together a test case, but it
sure does hurry thing along when you provide it :)

--
----------------------------------------------------------------------------
Louis Davidson - http://spaces.msn.com/members/drsql/
SQL Server MVP
"Arguments are to be avoided: they are always vulgar and often convincing."
(Oscar Wilde)

Show quote
"Abel Chan" <awong@newsgroup.nospam> wrote in message
news:2765C5A8-B8B7-4AA3-934D-E0EA887F701D@microsoft.com...
> Hi all,
>
> To clarify the issue, I provided an extract of the actual code.  Forgive
> me
> all (and Adam).  I should follow the best practice next time.
>
> Header Table:
>
> CREATE TABLE dbo.tbOrderHeader (
> intHeaderId int IDENTITY (1, 1) NOT NULL
> ,dtmInsertDate datetime NOT NULL
> ,dtmUpdateDate datetime NOT NULL
> ,tiRecordStatus tinyint NOT NULL
> )
>
> Detail Table:
>
> CREATE TABLE dbo.tbOrderDetail (
> intDetailId int IDENTITY (1, 1) NOT NULL
> ,intHeaderId               int NOT NULL
> ,dtmInsertDate datetime NOT NULL
> ,dtmUpdateDate datetime NOT NULL
> ,tiRecordStatus tinyint NOT NULL
> )
>
> Adjustment Table:
>
> CREATE TABLE dbo.tbAdjustment(
> intAdjustmentId int IDENTITY (1, 1) NOT NULL
> ,intDetailId               int NOT NULL
> ,dtmInsertDate datetime NOT NULL
> ,dtmUpdateDate datetime NOT NULL
> ,tiRecordStatus tinyint NOT NULL
> )
>
> Validation Table:
>
> CREATE TABLE dbo.tbValidation(
> intValidationId int IDENTITY (1, 1) NOT NULL
> ,intDetailId               int NOT NULL
> ,dtmInsertDate datetime NOT NULL
> ,dtmUpdateDate datetime NOT NULL
> ,tiRecordStatus tinyint NOT NULL
> )
>
> If joining Header and Detail returns some records, I need to find out
> whether there is any record under Adjustment and Validation.  There could
> be
> multiple records of Adjustment and validation under each detail record.
>
> When I think more carefully, I understand why my select statement won't
> work.  This is because there is no direct relationship between Adjustment
> and
> Validation.  They are just like separate child under the Detail table.  By
> using a single SELECT statement to return Header, Detail, Adjustment and
> Validation, the number of returning records will be:
>
> (# of records Joining Header and Detail) * Adjustment * Validation.
>
> That is exactly what happened.  I just need to create three separate
> SELECT
> statements to handle all the information.
>
> Thanks again.
>
> Abel
>
>

AddThis Social Bookmark Button