Jordan
Jordan

Reputation: 2758

SQL Query to retrieve tags with posts

So I have an SQL Table structure such that I have

  1. Blogs which have blogIDs
  2. BlogAffiliates which join with Blogs on BlogID [Gets people affiliated with that Blog]
  3. BlogPosts which join with Blogs on BlogID [Gets all posts for a blog]
  4. BlogPostPictures which join with BlogPosts on BlogPostID [Gets pictures for all posts for a given blog]

So I supply a username to match with BlogAffiliates which should get me all the BlogIDs associated with that user, which in turn gets me all blogs, which in turn gets me all blog posts, which in turn gets me all blogpost pictures.

This works fine. My problem is BlogPosts also have BlogPostTags which use a BlogPostID to match to a table of BlogPostTags.

I have the following query

    select * from BlogPosts,BlogAffiliates, Blogs, BlogPostPictures
      where BlogAffiliates.UserID = @UserID 
      and BlogPosts.BlogID = BlogAffiliates.BlogID
      and Blogs.BlogID = BlogAffiliates.BlogID and 
      BlogPosts.BlogPostID = BlogPostPictures.BlogPostID

This will get me a row of data including all the info I need for EACH blog post for a given user. How would I include the tags on this? The problem is I have many BlogPostTags for each BlogPost so I have no idea how to join or group this info ?? BlogPostTags has a BlogPotID which could join with BlogPosts. Would I need to return a copy of EACH row once for each tag including that tag? That seems like an explosion of data, whereas now 10 BlogPosts would return 10 rows if they each had 5 BlogPostTags that would be 50 rows?? Have I structured my tables poorly or am I missing some way to aggregate the tags into each row [I dont even care if they aggregate into 1 field and I delimit them or something and decode it on the other end of the query]

Thanks in advance!

Any ideas???

Upvotes: 0

Views: 141

Answers (1)

BonyT
BonyT

Reputation: 10940

Well it kind'a depends on what you want to do with the data.

Your table structure is fine.

If you want the same number of rows returned as current - i.e. 1 per affiliate per blogpost (assuming 1 per picture per blogpost?) then you'll need to package up the tags into a single column in the resultset.

Alternatively you could simply manage the full resultset in code:

For example you could have a BlogPost object which contained a collection of Tags - An ORM would handle this for you easily - alternatively use a datareader with a loop and iterate through building up the tag collection, moving onto the next record when the blogpostid changes.

In SQL - you could write a UDF to perform the same function.

CREATE FUNCTION [dbo].[GetTagsByBlogPostId] (
@BlogPostID int
)
RETURNS varchar(max)
AS
DECLARE @Tags @OUTPUT varchar(max)
SELECT @Tags = COALESCE(@Tags + ', ', '') + Tag
FROM BlogPostTags
where BlogPostId = @BlogPostId

RETURN @Tags END

Then in your SQL Statement above just append a call to the UDF to the SELECT statement:

 select * from BlogPosts,BlogAffiliates, Blogs, BlogPostPictures, dbo.GetTagsByBlogPostId(BlogPosts.BlogPostId)
  where BlogAffiliates.UserID = @UserID 
  and BlogPosts.BlogID = BlogAffiliates.BlogID
  and Blogs.BlogID = BlogAffiliates.BlogID and 
  BlogPosts.BlogPostID = BlogPostPictures.BlogPostID

Upvotes: 2

Related Questions