Suppose there is a MSSQL table, UserPost, that represents something user has posted, with these fields:
ID | dateAdded | parentPostID | postBody
A user in the system could create a Request, receive a Response, and then other users could Comment on the Response. Ie, Request <=1:many=> Reponse <=1:many=> Comment (think StackOverlow’s Question > Answer > Comment model-like).
All user posts (Request, Response and Comment) are represented by UserPost rows, where Request has parentPostID = null;; Responses’ parentPostID is the Request’s ID, and Comment’s parentPostID is the ID of the Response.
I need to output everything in a simple fashion:
Request 1
- Response A
-- Comment (i)
-- Comment (ii)
- Response B
-- Comment (i)
Request 2
...
Question: which SQL statement returns the needed information in the most usable way?
I’m struggling to write a three-way join between (UserPosts) as Requests [join] (UserPosts) as Responses [join] (UsersPosts) as Comments but am not sure this is the easiest way.
Bonus: is it possible to do this using C# Linq?
Can’t think of a way to do this in LINQ. I’ve removed unused columns. Luckily this is a bounded hierarchy. I’m using the new
hierarchyiddata type, which has the desired sort order:HierarchyIDs (as strings) look like
/GrandParent/Parent/Child/– so we construct values that look like this. Obviously, if we don’t have a grandparent (up_2nd.IDis null, since we can’t achieve 2 left joins as described), then we just want to construct/Parent/Child/– this is what the 1st COALESCE is helping us achieve. Similarly, if we can’t find any parents (bothup_1st.IDandup_2nd.IDare null), then both of the COALESCEs just turn into empty strings, and we end up construcing/ID/.You can add:
to your select list, if you want to track what level the item is (or use numerics instead, if desired)