Question: I have a table which stores comments, the comment can either come from another user, or another profile which are separate entities in this app. 

My original thinking was that the table would have both user\_id and profile\_id fields, so if a user submits a comment, it gives the user\_id leaves the profile\_id blank

is this right, wrong, is there a better way?

Answer: 
Whatever is the best solution depends IMHO on more than just the table, but also how this is used elsewhere in the application.

Assuming that the comments are all associated with some other object, lets say you extract all the comments from that object. In your proposed design, extracting all the comments require selecting from just one table, which is efficient. But that is extracting the comments without extracting the information about the poster of each comment. Maybe you don't want to show it, or maybe they are already cached in memory.

But what if you had to retrieve information about the poster while retrieving the comments? Then you have to join with two different tables, and now the resulting record set is getting polluted with a lot of NULL values (for a profile comment, all the user fields will be NULL). The code that has to parse this result set also could get more complex.

Personally, I would probably start with the fully normalized version, and then denormalize when I start seeing performance problems

There is also a completely different possible solution to the problem, but this depends on whether or not it makes sense in the domain. What if there are other places in the application where a user and a poster can be used interchangeably? What if a User is just a special kind of a Profile? Then I think that the solution should be solved generally in the user/profile tables. For example (some abbreviated pseudo-sql):

```
create table AbstractProfile (ID primary key, type ) -- type can be 'user' or 'profile'
create table User(ProfileID primary key references AbstractProfile , ...)
create table Profile(ProfileID primary key references AbstractProfile , ...)

```

Then any place in your application, where a user or a profile can be used interchangeably, you can reference the LoginID.
In the past I have used a centralized comments table and had a field for the fk\_table it is referencing.

eg: 

```
comments(id,fk_id,fk_table,comment_text)

```

That way you can use UNION queries to concatenate the data from several sources.

```
SELECT c.comment_text FROM comment c JOIN user u ON u.id=c.fk_id WHERE c.fk_table="user"
UNION ALL
SELECT c.comment_text FROM comment c JOIN profile p ON p.id=c.fk_id WHERE c.fk_table="profile"

```

This ensures that you can expand the number of objects that have comments without creating redundant tables.