Please start any new threads on our new site at https://forums.sqlteam.com. We've got lots of great SQL Server experts to answer whatever question you can come up with.

 All Forums
 SQL Server 2005 Forums
 Transact-SQL (2005)
 Left join produces too many rows

Author  Topic 

shawnmolloy
Yak Posting Veteran

93 Posts

Posted - 2008-10-19 : 08:02:17
I have two tables I'm trying to join:

Topics_Discussion
FK [UserID]

Topics_User
PK [UserID]

Topics_User has 20 rows. Topics_Discussion has 4 rows. I want to see only the 4 rows from Topics_Discussion, with the user data from Topics_User appended to the 4 rows, for a grand total of - you guessed it - 4 rows.

Currently, when I use this left join I get 80 rows. This is not the expected behavior.


select * from
Topics_Discussion d
left join
Topics_User u
on
d.userid = u.userid


How can I revise this join to do my bidding? Do I need a DISTINCT clause? I tried inner, outer, and right joins - to no avail.

Thanks,

-- shawn

webfred
Master Smack Fu Yak Hacker

8781 Posts

Posted - 2008-10-19 : 08:32:19
In this case left join returns all rows from Topics_Discussion and brings NULL for the columns of Topics_User when there are no matching userid.
You can add:
WHERE u.userid IS NOT NULL to exclude the not-matching-pairs.

Webfred

Planning replaces chance by mistake
Go to Top of Page

shawnmolloy
Yak Posting Veteran

93 Posts

Posted - 2008-10-19 : 09:46:30
I get the same result after adding the not null where clause:


select * from Topics_Discussion d
left join Topics_User u
on d.userid = u.userid
where u.userid IS NOT NULL


Here is a sample of the data if this helps:

Topics_Discussion:
userid id
----------- -----------
61 1
61 2
61 3
61 4

Topics_User:
userid nickname
----------- -----------------------
61 Shawn
61 Shawn
61 Shawn
61 Shawn
61 Shawn
61 Shawn
61 Shawn
61 Shawn
61 Shawn
61 Shawn
61 Shawn
61 Shawn
61 Shawn
61 Shawn
61 Shawn
61 Shawn
61 Shawn
61 Shawn
61 Shawn
61 Shawn

Again, I'm seeing 80 rows from these 20 rows in USER plus the 4 rows in DISUCSSION.

Thanks.

Go to Top of Page

webfred
Master Smack Fu Yak Hacker

8781 Posts

Posted - 2008-10-19 : 09:53:44
Now i see...
You can use a common table with distinct values to join:

;with my_topics_user (userid, nickname) as (select distinct userid, nickname from topics_user)
select * from Topics_Discussion d
left join my_topics_user u
on d.userid = u.userid
where u.userid IS NOT NULL

Webfred

Planning replaces chance by mistake
Go to Top of Page

shawnmolloy
Yak Posting Veteran

93 Posts

Posted - 2008-10-19 : 10:06:27
Cool, thanks WebFred - that does the trick. The whole "With" thing is kinda weird though. I don't understand why I can't just use a straight forward join with a distinct clause.

So what kind of join is it called when you use "with"? What exactly does "with" do to the two tables?

Thanks!
Go to Top of Page

webfred
Master Smack Fu Yak Hacker

8781 Posts

Posted - 2008-10-19 : 10:15:54
A common table expression is only one way to solve your problem from above.
It's just a resultset that you can use as a table.
I like the readability of this way.

For more info see:
http://msdn.microsoft.com/en-us/library/ms190766(SQL.90).aspx

Greetings
Webfred

Planning replaces chance by mistake
Go to Top of Page

shawnmolloy
Yak Posting Veteran

93 Posts

Posted - 2008-10-19 : 11:03:01
Common Table Expression, huh? I like it! Thanks for this new piece of knowledge, Fred.

Hey one last question, if you don't mind?

If I want to expand this query with another join, I assume I'd do this:


WITH my_topics_user (userid, nickname)
AS (SELECT DISTINCT userid, nickname
FROM [WiseTopic_topics_user])
SELECT e.*, d.* FROM [WiseTopic_Topics_Discussion] d
LEFT JOIN
my_topics_user u on d.userid = u.userid
LEFT JOIN
[WiseTopic_Topics_Category] e on e.categoryid = d.categoryid
where
u.userid IS NOT NULL


But there are two problems:

1) How do I add the columns from "e" (the new table; category)
2) Why now is the data redundant? What I mean is... now the results look like:

categoryId title
------------- -------------------
1 Politics
2 Aliens
1 Politics
2 Aliens

I musta done something screwy......
Go to Top of Page

webfred
Master Smack Fu Yak Hacker

8781 Posts

Posted - 2008-10-19 : 11:16:57
A short while ago i was surprised to see that your table Topics_User has so many entrys for the same User. I expected only one entry for one user...
Now there is a new table and i wanna know if there are redundant entries too.

The best practice is alwas to show the structure of the tables, example of data in each table and in relation to the example data what the resultset should contain.

Webfred

Planning replaces chance by mistake
Go to Top of Page

visakh16
Very Important crosS Applying yaK Herder

52326 Posts

Posted - 2008-10-19 : 13:10:25
quote:
Originally posted by webfred

A common table expression is only one way to solve your problem from above.
It's just a resultset that you can use as a table.
I like the readability of this way.

For more info see:
http://msdn.microsoft.com/en-us/library/ms190766(SQL.90).aspx

Greetings
Webfred

Planning replaces chance by mistake


why do you think CTE is needed for getting distinct rows? wont below work?

select * from Topics_Discussion d
inner join (select distinct userid, nickname
from Topics_User) u
on d.userid = u.userid


also if you want only matching rows why use left join and look for not null rows? isnt it enough just to do an inner join as in above?
Go to Top of Page

visakh16
Very Important crosS Applying yaK Herder

52326 Posts

Posted - 2008-10-19 : 13:15:24
quote:
Originally posted by shawnmolloy

Common Table Expression, huh? I like it! Thanks for this new piece of knowledge, Fred.

Hey one last question, if you don't mind?

If I want to expand this query with another join, I assume I'd do this:


WITH my_topics_user (userid, nickname)
AS (SELECT DISTINCT userid, nickname
FROM [WiseTopic_topics_user])
SELECT e.*, d.* FROM [WiseTopic_Topics_Discussion] d
LEFT JOIN
my_topics_user u on d.userid = u.userid
LEFT JOIN
[WiseTopic_Topics_Category] e on e.categoryid = d.categoryid
where
u.userid IS NOT NULL


But there are two problems:

1) How do I add the columns from "e" (the new table; category)
2) Why now is the data redundant? What I mean is... now the results look like:

categoryId title
------------- -------------------
1 Politics
2 Aliens
1 Politics
2 Aliens

I musta done something screwy......


the above output can be obtained just by doing below

SELECT e.*, d.* FROM [WiseTopic_Topics_Discussion] d
INNER JOIN
(SELECT DISTINCT userid, nickname
FROM [WiseTopic_topics_user]) u on d.userid = u.userid
LEFT JOIN
[WiseTopic_Topics_Category] e on e.categoryid = d.categoryid


and if category table also has duplicates use this

SELECT e.*, d.* FROM [WiseTopic_Topics_Discussion] d
INNER JOIN
(SELECT DISTINCT userid, nickname
FROM [WiseTopic_topics_user]) u on d.userid = u.userid
LEFT JOIN
(SELECT DISTINCT categoryid,title
FROM [WiseTopic_Topics_Category]) e on e.categoryid = d.categoryid

Go to Top of Page

webfred
Master Smack Fu Yak Hacker

8781 Posts

Posted - 2008-10-19 : 13:18:45
Hello Visa,
i have never intended that CTE is absolute needed but I Like It.
I have no preference for left join or (inner) join. I think it doesn't matter.

Greetings
Webfred

Planning replaces chance by mistake
Go to Top of Page

visakh16
Very Important crosS Applying yaK Herder

52326 Posts

Posted - 2008-10-19 : 13:22:32
quote:
Originally posted by webfred

Hello Visa,
i have never intended that CTE is absolute needed but I Like It.
I have no preference for left join or (inner) join. I think it doesn't matter.

Greetings
Webfred

Planning replaces chance by mistake


Ok. i was asking if it was really required. I always prefered to use derived tables to take distinct values as in above.Regarding joins i think its always better to use inner join when looking for exact matches as inner join seems to perform much better than left join.
Go to Top of Page

webfred
Master Smack Fu Yak Hacker

8781 Posts

Posted - 2008-10-19 : 13:27:48
OK, i will take that in mind the next time.

And in the join above it would be useful for the output to include u.nickname in selectlist wouldn't it?

Webfred

Planning replaces chance by mistake
Go to Top of Page

visakh16
Very Important crosS Applying yaK Herder

52326 Posts

Posted - 2008-10-19 : 13:50:43
quote:
Originally posted by webfred

OK, i will take that in mind the next time.

And in the join above it would be useful for the output to include u.nickname in selectlist wouldn't it?

Webfred

Planning replaces chance by mistake


yup. if OP needs it also. i just copied code posted and just changed the join & cte. dont know what all values OP wants.
Go to Top of Page

shawnmolloy
Yak Posting Veteran

93 Posts

Posted - 2008-10-21 : 23:27:33
Visakh. I changed my stored proc to use the join query example you have above and it produced the same results. I like that syntax much better as well, its easier to get your head around. Derived tables are the way to go.

And also, next time I post I'll be sure to post my database table structure as well. Speaking of, whats the best way to translate that info from the database to a forum post? I've tried changing the results in Query Analyzer to "Results to Text" (as opposed to grid) and pasting it, but that never works well. I could take a screen shot of the table schemas but that is a pain. Or I could just list out the column names and types, but is there a standard format for doing that?

Thanks.
Go to Top of Page

visakh16
Very Important crosS Applying yaK Herder

52326 Posts

Posted - 2008-10-22 : 00:17:51
quote:
Originally posted by shawnmolloy

Visakh. I changed my stored proc to use the join query example you have above and it produced the same results. I like that syntax much better as well, its easier to get your head around. Derived tables are the way to go.

And also, next time I post I'll be sure to post my database table structure as well. Speaking of, whats the best way to translate that info from the database to a forum post? I've tried changing the results in Query Analyzer to "Results to Text" (as opposed to grid) and pasting it, but that never works well. I could take a screen shot of the table schemas but that is a pain. Or I could just list out the column names and types, but is there a standard format for doing that?

Thanks.


no need of taking the screen shot. just copy from query analyser with option set to results to text and paste it here and remember to enclose with code tags (for this select the entire code you pasted and click # button on top menu). Also for instructions of how to post a question refer below link.

http://weblogs.sqlteam.com/brettk/archive/2005/05/25/5276.aspx
Go to Top of Page

shawnmolloy
Yak Posting Veteran

93 Posts

Posted - 2008-10-22 : 01:36:51
Thanks for the link; its a good read.

1. State the question
2. Post the DDL
3. Post sample DML
5. Post the expected results

Good rules to post by, I'll keep them in mind.
Go to Top of Page

visakh16
Very Important crosS Applying yaK Herder

52326 Posts

Posted - 2008-10-22 : 01:44:45
quote:
Originally posted by shawnmolloy

Thanks for the link; its a good read.

1. State the question
2. Post the DDL
3. Post sample DML
5. Post the expected results

Good rules to post by, I'll keep them in mind.


Cheers
This will also help us to give quick and accurate solutions for your questions.
Go to Top of Page
   

- Advertisement -