Unix Technical Forum

select parent records that do not have a particular child

This is a discussion on select parent records that do not have a particular child within the SQL Server forums, part of the Microsoft SQL Server category; --> Hi, I've got a many-many relationship between people and locations: Persons {personid, namefirst, accountid} Locations {locationid, locationname, accountid} // ...


Go Back   Unix Technical Forum > Database Server Software > Microsoft SQL Server > SQL Server

FAQ Members List Calendar Search Today's Posts Mark Forums Read
  #1 (permalink)  
Old 04-19-2008, 07:19 AM
d-42
 
Posts: n/a
Default select parent records that do not have a particular child

Hi,

I've got a many-many relationship between people and locations:

Persons {personid, namefirst, accountid}
Locations {locationid, locationname, accountid}

// many-many join table
PersonLocation {personid, locationid}

I want to find all the people who belong to a particular account, who
are not associated with a particular location.

For example:

ie: If I've got 4 people:

{1, Homer, x}
{2, Marge, x}
{3, Ned, x}
{4, Moe, x}
{5, Bullwinkle, y}

and two locations:

{1, Simpson's Home, x}
{2, Moe's Tavern, x}

and a match table as follows:
Homer has both the home, and the bar
Marge has just the home.
Ned has none.
Moe has just the bar.
Bullwinkle has none.

or records: {1,1}, {1,2}, {2,1},{4,2}

I want to find all the people who belong to account 'x', who are NOT
associated with Moe's Tavern.
i.e. -- I want to return just Marge and Ned.

I came up with this:

@P0 is the accountid I'm interested in.
@P1 is the locationid I'm interested in.

SELECT
[t0].[personid] AS [personid],
[t0].[namefirst] AS [namefirst],
[t0].[accountid] AS [accountid],
[t1].[locationid] AS [locationid]
FROM [dbo].[Persons] AS [t0]
LEFT OUTER JOIN
(SELECT [t2].[personid], [t2].[locationid] FROM [dbo].
[PersonLocation] AS [t2]
WHERE [t2].[locationid]=@P1)
AS [t1] ON [t0].[personid] = [t1].[personid]
WHERE
([t0].[accountid] = @P0) AND
([t1].[locationid] IS NULL)

This appears to work, but is it the best way?

Thanks,
Dave

Thanks,
Dave



Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
Reply With Quote
  #2 (permalink)  
Old 04-19-2008, 07:19 AM
Ed Murphy
 
Posts: n/a
Default Re: select parent records that do not have a particular child

d-42 wrote:

> I want to find all the people who belong to a particular account, who
> are not associated with a particular location.

[snip]
> SELECT
> [t0].[personid] AS [personid],
> [t0].[namefirst] AS [namefirst],
> [t0].[accountid] AS [accountid],
> [t1].[locationid] AS [locationid]
> FROM [dbo].[Persons] AS [t0]
> LEFT OUTER JOIN
> (SELECT [t2].[personid], [t2].[locationid] FROM [dbo].
> [PersonLocation] AS [t2]
> WHERE [t2].[locationid]=@P1)
> AS [t1] ON [t0].[personid] = [t1].[personid]
> WHERE
> ([t0].[accountid] = @P0) AND
> ([t1].[locationid] IS NULL)
>
> This appears to work, but is it the best way?


The following syntax allows you to say what you really mean:

select personid, namefirst
from Persons t0
where accountid = @P0
and not exists (
select *
from PersonLocation t2
where t2.personid = t0.personid
and t2.locationid = @P1
)
Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
Reply With Quote
  #3 (permalink)  
Old 04-19-2008, 07:19 AM
d-42
 
Posts: n/a
Default Re: select parent records that do not have a particular child

On Apr 18, 7:13 am, Ed Murphy <emurph...@socal.rr.com> wrote:
> d-42 wrote:
> > I want to find all the people who belong to a particular account, who
> > are not associated with a particular location.

> [snip]
> > SELECT
> > [t0].[personid] AS [personid],
> > [t0].[namefirst] AS [namefirst],
> > [t0].[accountid] AS [accountid],
> > [t1].[locationid] AS [locationid]
> > FROM [dbo].[Persons] AS [t0]
> > LEFT OUTER JOIN
> > (SELECT [t2].[personid], [t2].[locationid] FROM [dbo].
> > [PersonLocation] AS [t2]
> > WHERE [t2].[locationid]=@P1)
> > AS [t1] ON [t0].[personid] = [t1].[personid]
> > WHERE
> > ([t0].[accountid] = @P0) AND
> > ([t1].[locationid] IS NULL)

>
> > This appears to work, but is it the best way?

>
> The following syntax allows you to say what you really mean:
>
> select personid, namefirst
> from Persons t0
> where accountid = @P0
> and not exists (
> select *
> from PersonLocation t2
> where t2.personid = t0.personid
> and t2.locationid = @P1
> )


Thank you, yes, that is much more succint.

Unfortunately I can't seem to express this in linq (no 'exists'
keyword), but it has led me to a better way of expressing it in linq
than I was:

var q2 = from p in Persons
where p.account == accid
where !(from x in PersonDistLocation
where x.DistLocationID == distlocationid
select x.PersonID).Contains(p.PersonID)
select p;

which is much more readable than the linq I had, and its analogous to
what you've given me.
(linq is still using an outer join though, and I'm hoping the
performance is equivalent.)

Thanks,
Dave
Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
Reply With Quote
Reply


Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are On
Forum Jump


All times are GMT. The time now is 02:09 PM.


Powered by vBulletin® Version 3.6.5
Copyright ©2000 - 2008, Jelsoft Enterprises Ltd.
SEO by vBSEO 3.2.0
www.UnixAdminTalk.com