tags:

views:

237

answers:

4

Here is the situation. I have 3 tables, one super type, and two sub types, with a relationship between the sub types:

|----------------|    |-------------------| |-------------------|
|      Post      |    |     Top_Level     | |      Comment      | 
|----------------|    |-------------------| |-------------------| 
| PK | ID        |    | PK, FK | Post_ID  | | PK, FK | Post_ID  | 
|    | DATE      |    |        | Title    | |     FK | TopLv_ID | 
|    | Text      |    |-------------------| |-------------------| 
|----------------|

Each post, either comment or top_lev, is unique, but the entities share some attributes. So, comment and top_lev are sub types of post. That is one portion. Additionally, comments are associated with a top_lev post. This ER diagram illustrates this: http://img11.imageshack.us/img11/9327/sampleer.png

What I am looking for is a list of Top_Level posts ordered by activity on that top_level post, either creation of the top_level post, or a comment on that post.

For example, assume we have the following data:

|------------------------|    |------------------|    |--------------------|
|      Post              |    |     Top_Level    |    |       Comment      |
|------------------------|    |------------------|    |--------------------|
| ID |    DATE    | Text |    | Post_ID  | Title |    | Post_ID  |TopLv_ID |
|----|------------|------|    |----------|-------|    |----------|---------|
|  1 | 13/03/2008 | shy  |    |     1    |  XYZ  |    |     2    |    1    |
|  2 | 14/03/2008 | mrj  |    |     3    |  ABC  |    |     4    |    1    |
|  3 | 15/03/2008 | quw  |    |     7    |  NMO  |    |     5    |    3    |
|  4 | 16/03/2008 | ksi  |    |------------------|    |     6    |    1    |
|  5 | 17/03/2008 | kso  |                            |--------------------|
|  6 | 18/03/2008 | aoo  |                            
|  7 | 19/03/2008 | all  |                            
|------------------------|     

|--------------------------------|
|            RESULT              |
|--------------------------------|
| ID |    DATE    | Title | Text |
|----|------------|-------|------|
|  7 | 19/03/2008 |  123  | all  |
|  1 | 13/03/2008 |  ABC  | shy  |
|  3 | 15/03/2008 |  XYZ  | quw  |
|--------------------------------|

Can this be done with a single select statement? If so, how?

A: 

That should definitely be possible, as long as "date of the last occurrence" is represented in a column of Sub1 and Sub2. Note that the code I'm listing is mostly pseudocode... you'll have to fill in the blanks according to your flavor of dbms.

To limit your result-set to only the columns in SUPER and SUB1 (with no dupes):

SELECT DISTINCT sub1.*, super.*

(obviously, you should try to avoid SELECT *... pick which columns you actually need)

You FROM clause would look something like:

FROM super INNER JOIN sub1 ON super_id
    LEFT JOIN sub2 ON super_id AND sub1_id

And ORDER BY would use the COALESCE function (if your dbms supports it) to figure out which column to sort by (COALESCE chooses the first non-null value in the argument list):

ORDER BY COALESCE(sub2.dateColumn, sub1.dateColumn)

Alternatively, if you don't have COALESCE available but you do have an ISNULL function available, you can chain ISNULLs:

ORDER BY ISNULL(firstDateColumn, ISNULL(secondDateColumn, thirdDateColumn))
dkeen
Using MySQL, "SELECT DISTINCT sub1.*, super.* FROM super INNER JOIN sub1 ON sub1.super_id LEFT JOIN sub2 ON sub2.super_id AND sub2.sub1_id" gives each sub1 for each super, giving NxM rows rather than just M.
cdeszaq
+1  A: 

You've perhaps unintentionally pretty thoroughly obfuscated your question, making it very difficult to understand and answer (at least for those of us with small brains.) Could you possibly restate it with reasonable table and field names, and a more complete description of indexes?


EDIT:

Are you possibly describing a situation where products are sold, and also sometimes the same products can be included as components in other products recursively? If so, there are more conventional successful ways to model the situation.

le dorfier
I have made the tables a bit more real. The example is still quite contrived, but is at least more comprehensible. Does that help?
cdeszaq
What's the difference between an item, a product, and a component? And your example simply shows IDs for the 3 products, with their dates from the first table. What effect did the other two tables have, and why?
le dorfier
And the earliest buy_date in the list is 13-03-2008, for Product 1, but it's second in the list.
le dorfier
The example now should be much more comprehensible...it should work similarly to the SO front page.
cdeszaq
A: 

You didn't suggest or hint that the schema could be re-designed, so perhaps my asking this question isn't the best use of your time and mine, but: do your tables have to be designed this way? Is this application already in production use?

What triggered this thought in my head was your statement:

All events happen at a date, but edits must be associated with the original creation event

I suspect that this is the rationale for having sub2 include a FK to sub1. But this feels to me like a denormalization (in relational terms) or a violation of the DRY principle (in Agile terms.) In either case, it may make your life more complicated than it needs to be.

My advice (worth what you're paying for it) would be to remove the FK to sub1. In its place, you can either 1) include a SELECT on the creation event for the page, as part of the query, or 2) Move the creation date into the page table. (Which of these options you take depends on how much additional complexity exists in the schema; I'd usually prefer #1 over #2.)

I would think that this would simplify your updates as well as your queries. Your mileage may vary.

Dan Breslau
I have updated the question to be a bit more clear. In my case, there is a clear supertype with 2 subtypes sort of relationship, but there is also a relationship between the two subtypes. The schema is NOT set, but since there truly is such a super/sub type relationship, this is the most "normal".
cdeszaq
Your discussion of supertypes, subtypes, and relationships is not one I normally encounter in the context of discussing the normalization of a relational database. Are you confusing your conceptual frameworks?
le dorfier
The reason for having sub/super-type tables is to normalize. Identifying these relationships is the core of normalization. Otherwise, one lump table, with massive data replication, would suffice. However, a more normal DB is desired in this case.
cdeszaq
Please provide some other kind of guidance -- an entity relationship diagram, perhaps. I cannot make heads or tails of what you're trying to achieve, and from what I gather, neither can anyone else.
Dan Breslau
Hint: I'd expect that all Comments having the same FK to Top_Level, would also have the same FK to Post; and that the shared Top_Level would also have the same FK to Post. Please help me understand why that's not the case.
Dan Breslau
Each post, either comment or top_lev, is unique. So, comment and top_lev are sub types of post. That is one portion. Additionally, comments are associated with a top_lev post. This ER diagram illustrates this: http://img11.imageshack.us/img11/9327/sampleer.png
cdeszaq
Your example shows a Comment where Post_ID=7 and TopLv_ID=3, and a Top_Level entry where PostID=7. Either these are errors in the example, or the relationships are still very unclear.
Dan Breslau
Thank you, it was an error.
cdeszaq
+1  A: 

I tried this query and it gives the output you describe:

SELECT pt.id, pt.`date`, t.title, pt.`text`
FROM Top_Level t INNER JOIN Post pt ON (t.post_id = pt.id)
 LEFT OUTER JOIN (Comment c INNER JOIN Post pc ON (c.post_id = pc.id))
   ON (c.toplv_id = t.post_id)
GROUP BY pt.id
ORDER BY MAX(GREATEST(pt.`date`, pc.`date`)) ASC;

Output:

+----+------------+-------+------+
| id | date       | title | text |
+----+------------+-------+------+
|  7 | 2008-03-19 | NMO   | all  | 
|  1 | 2008-03-13 | XYZ   | shy  | 
|  3 | 2008-03-15 | ABC   | quw  | 
+----+------------+-------+------+
Bill Karwin