July 25, 2005 at 6:19 am
I need to know how to use a join which will only take one result from the left hand table of the join and not create duplicates in the right hand (original) table.
For example I am querying a book table, and an authors table, but for the purposes of my output I want only to display ONE author per book and not two (as is sometimes the case with the data I am working with)
How can I accomplish this with just one sql query?
this is the query I am currently using which produces duplicates on the right:
select * from Book B
inner join bookContributor on B.bookID = bookcontributor.bookID
inner join contributor on bookcontributor.contributorid = contributor.contributorid
thanks in advance for your help
July 25, 2005 at 6:44 am
I'm assuming you mean you can have more than one author to a book and you want to show only 1 ?
It would help to have the structure of the tables..but you can use a subquery in the join to isolate a single author.
--M Kulangara
Mathew J Kulangara
sqladventures.blogspot.com
July 25, 2005 at 6:56 am
Yes there can be more than one author per book, and I would very much like to isolate only one.
The Book table stores generic data about the book; Title, Description, ISBN etc. The BookContributor table is a link table which contains BookID's and ContributorID's - this is a many to many situation. The Contriburor table stores information about Authors, specifically the Names which I am interested in.
can you show me an example of a subquery that you mention to achieve this result ?
July 25, 2005 at 7:32 am
Tom if you could supply us with your table structure, some sample data and the expected results we could supply you with the informaton your requested.
Mike
July 25, 2005 at 7:59 am
SET NOCOUNT ON
DECLARE @Book TABLE
(
bookID INT,
BookName VARCHAR(100)
)
DECLARE @Contributor TABLE
(
contributorid INT,
Contributor VARCHAR(100)
)
DECLARE @bookContributor TABLE
(
bookID INT,
contributorid INT
)
INSERT INTO @Book VALUES (1, 'Book1')
INSERT INTO @Book VALUES (2, 'Book2')
INSERT INTO @Book VALUES (3, 'Book3')
INSERT INTO @Book VALUES (4, 'Book4')
INSERT INTO @Book VALUES (5, 'Book5')
INSERT INTO @Book VALUES (6, 'Book6')
INSERT INTO @Contributor VALUES (1, 'Contributor1')
INSERT INTO @Contributor VALUES (2, 'Contributor2')
INSERT INTO @Contributor VALUES (3, 'Contributor3')
INSERT INTO @Contributor VALUES (4, 'Contributor4')
INSERT INTO @Contributor VALUES (5, 'Contributor5')
INSERT INTO @Contributor VALUES (6, 'Contributor6')
INSERT INTO @bookContributor VALUES (1, 1)
INSERT INTO @bookContributor VALUES (2, 1)
INSERT INTO @bookContributor VALUES (3, 1)
INSERT INTO @bookContributor VALUES (4, 2)
INSERT INTO @bookContributor VALUES (5, 6)
INSERT INTO @bookContributor VALUES (6, 3)
INSERT INTO @bookContributor VALUES (6, 4)
INSERT INTO @bookContributor VALUES (6, 5)
/* Your query likely to give duplicates if the data is having duplicates */
select * from @Book B
inner join @bookContributor bc
on B.bookID = bc.bookID
inner join @contributor c
on bc.contributorid = c.contributorid
/* This query will give the unique author per book */
/* This is not correct. Put possible in TSQL */
/* If more than one author is there which one to choose. This query choses the first */
/* I would say you should correct the data */
/* There is no need for bookContributor table */
/* Just Add contributorid in the Book table */
SELECT B.BookName, C.Contributor
FROM
@Book B
INNER JOIN
(
SELECT bookID, MIN(contributorid) contributorid FROM @bookContributor
GROUP BY bookID) bc
ON B.bookID = bc.bookID
INNER JOIN
@contributor c
ON bc.contributorid = c.contributorid
Regards,
gova
July 25, 2005 at 8:07 am
Hi Guys
Lets say our book table looks something like this:
BookID (int PK) Title ISBN
1 Into the Storm 12345
our Contributor table looks like:
ContributorID FirstName LastName
1 Tom Clancy
2 Fred Franks
and the BookContributor table looks like:
BookContributorID BookID ContributorID
1 1 1
2 1 2
Now when I execute my query:
select * from Book B
inner join bookContributor on B.bookID = bookcontributor.bookID
inner join contributor on bookcontributor.contributorid = contributor.contributorid
I am going to see TWO results returned for one Book. I actually only want to see one record coming back, and I dont particularly mind which Author comes out.
I need to know the solution not only for this scenario, but for others like this which I have encountered too, where you see duplication of results in the source table which is not wanted.
Previously I have solved this kind of problem by Hitting the DB twice which I am sure you agree is not ideal in a web situation.
thanks..
t
July 25, 2005 at 8:09 am
govinn, thanks!
Looks like you given me the lead I needed. I had no idea you could join a subquery like that.
July 25, 2005 at 8:13 am
OK. Anyone know how I might go about getting BOTH authors names into a single text/varchar field and have unique book results?
July 25, 2005 at 8:14 am
Your book contributor table holds the book ID, and the author ID, right?
And, when you query this table, you want the book ID, with only ONE author, even if others exist.
Let's assume that the first author entered is always the author that you want.
Select BookID, min(AuthorID)
from BookContributor
Group by BookID
We then build our query using this as a derived table.
select *
from BookTable b
join (Select BookID, min(AuthorID) as MinID
from BookContributor
Group by BookID) c
on b.BookID = c.BookID
July 25, 2005 at 8:17 am
SET NOCOUNT ON
DECLARE @Book TABLE
(
bookID INT,
ISBN VARCHAR(100)
)
DECLARE @Contributor TABLE
(
contributorid INT,
FirstName VARCHAR(100),
LastName VARCHAR(100)
)
DECLARE @bookContributor TABLE
(
BookContributorID INT,
bookID INT,
contributorid INT
)
INSERT INTO @Book VALUES (1, '12345')
INSERT INTO @Contributor VALUES (1, 'Tom', 'Clancy')
INSERT INTO @Contributor VALUES (2, 'Fred', 'Franks')
INSERT INTO @bookContributor VALUES (1, 1, 1)
INSERT INTO @bookContributor VALUES (2, 1, 2)
/* Your query */
select * from @Book B
inner join @bookContributor bookContributor on B.bookID = bookcontributor.bookID
inner join @contributor contributor on bookcontributor.contributorid = contributor.contributorid
/* Your Answer */
select * from @Book B
inner join (select bookID, min(contributorid) contributorid from @bookContributor
group by BookID) bookContributor on B.bookID = bookcontributor.bookID
inner join @contributor contributor on bookcontributor.contributorid = contributor.contributorid
Regards,
gova
July 25, 2005 at 8:18 am
HTH
Regards,
gova
July 25, 2005 at 8:23 am
id try something like this..
go
create table author_prec
(
author_prec_id int identity(1,1),
rank int not null,
contributor_id int not null,
constraint AK_author_pred_rank Unique(rank),
constraint FK_author_pred_cont_id foreign key(contributor_id)
references contributor(contributor_id)
)
go
--we rank authors so that the lowest rank will be given precedence
Select B.Title, q.AuthorName
from Books B
join
(select c.bookid,c2.AuthorName,min(rank)
from bookContributors C
join contributor C2
on C2.contributorid = C.contributorid
join author_prec pre
on pre.contributor_id = c2.contributor_id
group by c.bookid,c2.AuthorName
)Q
on Q.bookid = B.Bookid
where q.authorName in (select top 1 q.authorname from Q order by rank asc)
Mathew J Kulangara
sqladventures.blogspot.com
July 25, 2005 at 9:49 am
I have a ContributorSequenceNumber column on the BookContributor table which has either and int, or a null in it. I need to have the lowest Int Number as my Author in the result set.
How would I do that?
t
July 25, 2005 at 11:37 am
Why do use null there ? What does that mean(that the book only has 1 author ?)
I would default that value to 0.
Then you can use what is below.
Select B.Title,C2.AuthorName
from Books B
join BookContributor C
on B.Bookid = C.Bookid
and c.Contributorid in
(select contributorid from (select Contributorid,min(isnull(ContributorSequenceNumber,0))
from BookContributor C2
where c2.Bookid = B.Bookid
group by contributorid)k)
join Contributor C2
on C2.contributorid = C.contributorid
group by B.Title,C2.AuthorName
Note ...I havent parsed this in QA..but hopefully the logic helps...
--M Kulangara
July 26, 2005 at 2:54 am
I not following the logic here
and I can't get that to parse in QA.
Think I need another coffee.
Viewing 15 posts - 1 through 15 (of 15 total)
You must be logged in to reply to this topic. Login to reply