SQL for Threaded Discussion ForumsBy Bill Graziano on 4 February 2001 | Tags: Application Design One of questions we get on a regular basis involves threaded discussion forums. Everyone wants to know an easy way to do this. Everyone is also trying to do recursive SQL or self joins to make this work. That's hard. Here's an easy way to do this. (UPDATE: Fixed a problem and thought I'd repost for everyone to see the changes)
UPDATE (2/4/01): Carlos discovered a little error with the stored procedure that would allow posts to get out of order. I added the two lines in red to the stored procedure below.
When you first look at this problem your first thought IS to use some type of self join or a recursive stored procedure into a temp table. Those are hard to write and hard to test. As you should know by now, I'm lazy and I wanted an easier way. One of my fundamental principles of database design is this: If you can't get data in or out easily, you're not storing it right. Let start with a table that looks like this:
PostID is my single field Primary Key for this table. I'm a huge fan of a single field primary key. It makes joins and subqueries so much easier. ThreadID is the field I'm going to use to keep all the posts in a thread together. The ThreadID is going to be the PostID of the first post in a thread (which is a post with a PostLevel = 1 ). ParentID is the PostID of the parent of this post. For the first post in a thread, ParentID will be set to the PostID. The first post in a thread will have the PostLevel equal 1. It's child posts are PostLevel = 2 and so on. Subject is the user entered subject and PostDate is the date and time the post was put into the database. I don't have a field for the actual post in this example. I wanted to keep this simple. You can easily add a varchar or text field to hold the users post. SortOrder is the key to this whole crazy scheme. That's the field I'm going to use to order the posts. My trick is to always keep the data sorted just like I want it in the table. That means my queries need to do as little work as possible. Let's take a look at a SELECT statment to display a threaded discussion:
and the output it generates:
As you can see my SELECT statement is pretty darn simple. Add an index on ThreadID and SortOrder and you'll get great performance. This is very important in this type of application. Most of the transactions against this table are going to be queries so this needs to be optimized to maximize query response time. Looking at the simplicity of this query I think you'll agree we've done that. In this example I've used the SPACE function to generate my indents. In your application you'll probably do that in ASP, VB or whatever you're writing in. The key to this approach is getting the records in the database in the right order. All the work is done in the stored procedure that puts the records into the table. Which looks like this:
So let's break down this procedure. The first main section handles a new post at the top level. That's pretty easy. I insert the record and update the record using the identity value generated. I'm sure there are faster ways to do that but I'm all about simple. The next case is replying to a post. The two options are a reply in the middle of a thread or appending to the end. Appending to the end is pretty easy. It's just like adding a new record. Putting a record in the middle is difficult. That is where the SortOrder field comes into play. We always keep this table sorted just like we want it to display. I have to "move down" the existing posts to insert a new one. I've also thought about writing a stored procedure to generate this type of table given a parent child relationship in a table. All you really need to do is run through the original table and call this stored procedure for each record. This will put them in the proper order. Hope this helps. Let me know how this works for you or if there's anything you'd like me to change. I'd suggest you test this strongly. I haven't had as much time to test it as I'd like. UPDATE (2/4/01): And it looks like that last sentence proved prophetic. -graz |
- Advertisement - |