Author |
Topic |
JBelthoff
Posting Yak Master
173 Posts |
Posted - 2010-11-27 : 16:11:58
|
Hi all,I have a table with an ID and ParentID that I am doing a recursive common table expression. It lists States, and then the States children. However I want it to order on alphbetical States and then thier children and I am usure how to do that. I would appreciate any help please...So I have this:ID PID DisplayName Level-------------------- -------------------- ------------------------- -----------1 0 New Jersey 02 1 Central Jersey 13 1 Jersey Shore 14 1 North Jersey 15 1 South Jersey 16 0 New York 07 6 Bronx 18 6 Brooklyn 19 6 Long Island 110 6 Queens 111 6 Manahatten 112 0 Connecticut 013 12 Eastern Connecticut 114 12 Hartford 115 12 New Haven 116 12 Northwest Connecticut 1 But I want this:ID PID DisplayName Level-------------------- -------------------- ------------------------- -----------12 0 Connecticut 013 12 Eastern Connecticut 114 12 Hartford 115 12 New Haven 116 12 Northwest Connecticut 11 0 New Jersey 02 1 Central Jersey 13 1 Jersey Shore 14 1 North Jersey 15 1 South Jersey 16 0 New York 07 6 Bronx 18 6 Brooklyn 19 6 Long Island 110 6 Queens 111 6 Manahatten 1 Here is the code I am currently using:;With cte_Location As ( Select e.ID, e.PID, e.DisplayName, 0 As [Level] From dbo.Locations As e Where e.PID = 0 Union All Select e.ID, e.PID, e.DisplayName, [Level] + 1 From dbo.Locations As e Inner Join cte_Location As d On e.PID = d.ID )Select ID, PID, Cast(DisplayName as varchar(25)) DisplayName, [Level]From cte_Location Order By ID, Level Any help would be appreciated. Thanks,JBelthoff› As far as myself... I do this for fun! |
|
dataguru1971
Master Smack Fu Yak Hacker
1464 Posts |
Posted - 2010-11-27 : 17:03:59
|
Messy, but in my defense, I am half drunk. With cte_LocationAS( Select e.ID, e.PID,e.DisplayName,ROW_NUMBER() OVER (ORDER BY e.DisplayName)*100 as [LEVEL] From dbo.Locations As e Where e.PID = 0 UNION ALL Select e.ID, e.PID, e.DisplayName, d.Level+ (ROW_NUMBER() OVER (ORDER BY e.DisplayName)) as [LEVEL] From dbo.Locations As e inner Join (Select e.ID, e.PID,e.DisplayName,ROW_NUMBER() OVER (ORDER BY e.DisplayName)*100 as [LEVEL] From dbo.Locations As e Where e.PID = 0) As d On e.PID = d.ID )Select * FROM cte_LocationOrder by Level I get this:ID PID DisplayName LEVEL12 0 Connecticut 10013 12 Eastern Connecticut 10414 12 Hartford 10515 12 New Haven 10916 12 Northwest Connecticut 1111 0 New Jersey 2002 1 Central Jersey 2033 1 Jersey Shore 2064 1 North Jersey 2105 1 South Jersey 2136 0 New York 3007 6 Bronx 3018 6 Brooklyn 3029 6 Long Island 30711 6 Manahatten 30810 6 Queens 312 Poor planning on your part does not constitute an emergency on my part. |
 |
|
JBelthoff
Posting Yak Master
173 Posts |
Posted - 2010-11-27 : 17:09:06
|
Awesome Thank you very much!!!!!JBelthoff› As far as myself... I do this for fun! |
 |
|
dataguru1971
Master Smack Fu Yak Hacker
1464 Posts |
Posted - 2010-11-27 : 17:10:03
|
Check my edit...I had to post the right thing...need the *100 , not *10 or it gets whacked. Poor planning on your part does not constitute an emergency on my part. |
 |
|
JBelthoff
Posting Yak Master
173 Posts |
Posted - 2010-11-27 : 17:45:11
|
Yes I already anticipated that. Depening on how many total children there could be determines the *100 or greater.Thanks again! JBelthoff› As far as myself... I do this for fun! |
 |
|
dataguru1971
Master Smack Fu Yak Hacker
1464 Posts |
Posted - 2010-11-27 : 17:54:16
|
You are welcome.Edit: Now that I thinking clearly..it would be far more practical two separate this into two tables to begin with...have a State table, and a SubState table which contains the state id...not sure why you chose this table structure... Poor planning on your part does not constitute an emergency on my part. |
 |
|
Vinnie881
Master Smack Fu Yak Hacker
1231 Posts |
Posted - 2010-11-28 : 00:12:29
|
I would also suggest to use 2 seperate tablesif it's only 2 levels, you can use;With cte_Location As ( Select e.ID, e.PID, e.DisplayName, 0 As [Level],e.displayname as sort From dbo.Locations As e Where e.PID = 0 Union All Select e.ID, e.PID, e.DisplayName, [Level] + 1,d.displayname as sort From dbo.Locations As e Inner Join cte_Location As d On e.PID = d.ID )Select ID, PID, Cast(DisplayName as varchar(25)) DisplayName, [Level]From cte_Location Order By sort, Level,id Success is 10% Intelligence, 70% Determination, and 22% Stupidity.\_/ _/ _/\_/ _/\_/ _/ _/- 881 |
 |
|
Vinnie881
Master Smack Fu Yak Hacker
1231 Posts |
Posted - 2010-11-28 : 00:21:48
|
here's a better version of my above query that will work regardless of levels. ;With cte_Location As ( Select e.ID, e.PID, e.DisplayName, 0 As [Level],cast(e.displayname as varchar(200)) as sort From dbo.Locations As e Where e.PID = 0 Union All Select e.ID, e.PID, e.DisplayName, [Level] + 1,cast(sort + d.displayname as varchar(200)) as sort From dbo.Locations As e Inner Join cte_Location As d On e.PID = d.ID )Select ID, PID, Cast(DisplayName as varchar(25)) DisplayName, [Level]From cte_Location Order By sort,id Success is 10% Intelligence, 70% Determination, and 22% Stupidity.\_/ _/ _/\_/ _/\_/ _/ _/- 881 |
 |
|
dataguru1971
Master Smack Fu Yak Hacker
1464 Posts |
Posted - 2010-11-28 : 06:22:58
|
Nice..thanks Vinnie for the improvement. I didn't think you could use the CTE within itself, but that works nicely. Poor planning on your part does not constitute an emergency on my part. |
 |
|
X002548
Not Just a Number
15586 Posts |
|
dataguru1971
Master Smack Fu Yak Hacker
1464 Posts |
Posted - 2010-11-28 : 12:56:21
|
I think I noted that above...but it isn't against policy to offer a solution of some sort..even if the structure is not ideal..is it? Poor planning on your part does not constitute an emergency on my part. |
 |
|
X002548
Not Just a Number
15586 Posts |
|
Jeff Moden
Aged Yak Warrior
652 Posts |
Posted - 2010-11-28 : 16:56:58
|
quote: Originally posted by X002548 Gee...I was gonna say to normalize the data...Brett
Ok... now that you've said that, how would you "normalize" hierarchical data? --Jeff Moden |
 |
|
Vinnie881
Master Smack Fu Yak Hacker
1231 Posts |
Posted - 2010-11-28 : 17:10:38
|
He was referring to the State should not be kept in the same table with the city. That would greatly simplify the query for this scenerio, or future ones he will run into.Declare @mystate table(stateid int,mystatedesc varchar(20))Declare @mycity table(id int,stateid int, mycitydesc varchar(20))insert into @mystate(stateid,mystatedesc)select 1,'Connecticut' union allselect 2,'New York'insert into @mycity(id,stateid ,mycitydesc)select 1,1,'hartford' Union allselect 2,1,'New haven' Union allselect 3,2,'Bronx' Union allselect 4,2,'Brookland' --Then to query the appropriate data is much simplerselect * from@mystate ainner join@mycity bon a.stateid = b.stateidorder by mystatedesc Success is 10% Intelligence, 70% Determination, and 22% Stupidity.\_/ _/ _/\_/ _/\_/ _/ _/- 881 |
 |
|
Jeff Moden
Aged Yak Warrior
652 Posts |
Posted - 2010-11-29 : 09:43:50
|
That certainly works for this problem. Of course, this problem only has two levels in the "hierarchy". If it had, say, 10 levels, it would be a horse of a different color. ;-)--Jeff Moden |
 |
|
denis_the_thief
Aged Yak Warrior
596 Posts |
Posted - 2010-11-29 : 16:23:07
|
quote: Originally posted by Vinnie881 here's a better version of my above query that will work regardless of levels. ;With cte_Location As ( Select e.ID, e.PID, e.DisplayName, 0 As [Level],cast(e.displayname as varchar(200)) as sort From dbo.Locations As e Where e.PID = 0 Union All Select e.ID, e.PID, e.DisplayName, [Level] + 1,cast(sort + d.displayname as varchar(200)) as sort From dbo.Locations As e Inner Join cte_Location As d On e.PID = d.ID )Select ID, PID, Cast(DisplayName as varchar(25)) DisplayName, [Level]From cte_Location Order By sort,id
This solution is safer than the solution that suggested to multiply by 100 or whatever but even safer would be to change the above line to: Select e.ID, e.PID, e.DisplayName, [Level] + 1,cast(sort + '\' + d.displayname as varchar(200)) as sortsince '1' + '12' is not the same as '11' + '2'! |
 |
|
Vinnie881
Master Smack Fu Yak Hacker
1231 Posts |
Posted - 2010-11-29 : 22:04:35
|
A separator would ensure the sort field was always isolated, but it would also be far more likely that an issue would be the varchar(200) being too short than the sort issue you mentioned (using States and Cities as illustrated, there is close to no chance of a incorrect sort that I can think of, but if multiple levels were introduced I can see that field exceeding 200 characters).I am pointing this out because changing the sort field how you mentioned might make this a "Safer" query, but until you properly modify the ENTIRE query for a live scenario and the data you will use, it is not a "Safe" query, nor is it intended in any way to be interpreted as that. It was written to show a method, and prior to using it in a live scenario it should be modified to fit someone's needs. |
 |
|
denis_the_thief
Aged Yak Warrior
596 Posts |
Posted - 2010-11-30 : 09:33:40
|
sure, varchar(2000), even safer.Here's a scenario showing the separator could be essential:ID PID DisplayName Sort without separator-------------------- -------------------- ------------------------- -----------11 0 New Jersey 1102 11 Central Jersey 1121 0 Connecticut 1012 1 Eastern Connecticut 112Oh I'm sure this is a bad example. But even if we can't come up with a good example that will fail, better to be safe in case the user comes up with a good example that will fail. |
 |
|
Vinnie881
Master Smack Fu Yak Hacker
1231 Posts |
Posted - 2010-11-30 : 13:27:50
|
Maybe I didn't state that very clearly, I am agreeing with you that it was very good modification. I was just pointing out the query as presented was to illustrate a method, and if the goal was to make it safer, there would be more obvious modifications you would make prior to implementing in a live scenario. The examples you provided, and even "New York, New York" should still have sorted correctly in theory(I am actually interested for just personal curiosity if there is any combination of city and states at any level that it would not sort correctly).Even though it's not related to anything, if anyone is bored and can think of a combination, let me know, I'm curious now!Thanks Success is 10% Intelligence, 70% Determination, and 22% Stupidity.\_/ _/ _/\_/ _/\_/ _/ _/- 881 |
 |
|
denis_the_thief
Aged Yak Warrior
596 Posts |
Posted - 2010-11-30 : 13:44:09
|
I just realized I misread the code anyways.I was involved with a project and we used as a sort column: ChildID + '\' + ParentIDIt worked well for what we were doing but I guess the situation is this post is different anyways. |
 |
|
|