views:

435

answers:

5

I have recently stumbled upon a problem with selecting relationship details from a 1 table and inserting into another table, i hope someone can help.

I have a table structure as follows:

ID (PK)   Name       ParentID<br>
1         Myname     0<br>
2         nametwo    1<br>
3         namethree  2

e.g

This is the table i need to select from and get all the relationship data. As there could be unlimited number of sub links (is there a function i can create for this to create the loop ?)

Then once i have all the data i need to insert into another table and the ID's will now have to change as the id's must go in order (e.g. i cannot have id "2" be a sub of 3 for example), i am hoping i can use the same function for selecting to do the inserting.

+2  A: 

For the retrieval part, you can take a look at Common Table Expression. This feature can provide recursive operation using SQL.

For the insertion part, you can use the CTE above to regenerate the ID, and insert accordingly.

Adrian Godong
+3  A: 

If you are using SQL Server 2005 or above, you may use recursive queries to get your information. Here is an example:

With tree (id, Name, ParentID, [level])
As (
    Select id, Name, ParentID, 1
    From [myTable]
    Where ParentID = 0

    Union All

    Select child.id
       ,child.Name
       ,child.ParentID
       ,parent.[level] + 1 As [level]
    From [myTable] As [child]
    Inner Join [tree] As [parent]
    On [child].ParentID = [parent].id)
Select * From [tree];

This query will return the row requested by the first portion (Where ParentID = 0) and all sub-rows recursively. Does this help you?

I'm not sure I understand what you want to have happen with your insert. Can you provide more information in terms of the expected result when you are done?

Good luck!

Chris Nielsen
hi there, in terms of my completed structure i require a new table with the same structure as the select table but it would have to be in ID order, e.g. id 1 can have a sub section but it must be of an id > 1 and so on and so forth and must be in order e.g ID 1 top level, sub level, lower level, ID 2 toplevel, ID 3 toplevel, sub level. etc Hope this helps. Look forward to your reply.
The order of rows in a table is not defined. I don't think you're going to be able to guarantee the order of rows as they exist in the table itself. They best you can do is get things in a certain order when you pull them out with a SELECT statement, using the ORDER BY clause. In my example, you could add ORDER BY [level] to the select statement and this would guarantee that you won't get any parent rows coming after their children. Does that help?
Chris Nielsen
hi there, thanks again for your response. I decided to go ahead with a order by clause just before you posted back :) i am happy now i can insert in the correct order using a executescalar and returning the last id inserted ready for the next row insert.
+1  A: 

I hope this URL helps Self-Joins in SQL

essamSALAH
A: 

This is the problem of finding the transitive closure of a graph in sql. SQL does not support this directly, which leaves you with three common strategies:

  1. use a vendor specific SQL extension
  2. store the Materialized Path from the root to the given node in each row
  3. store the Nested Sets, that is the interval covered by the subtree rooted at a given node when nodes are labeled depth first

The first option is straightforward, and if you don't need database portability is probably the best. The second and third options have the advantage of being plain SQL, but require maintaining some de-normalized state. Updating a table that uses materialized paths is simple, but for fast queries your database must support indexes for prefix queries on string values. Nested sets avoid needing any string indexing features, but can require updating a lot of rows as you insert or remove nodes.

If you're fine with always using MSSQL, I'd use the vendor specific option Adrian mentioned.

Jason Watkins
Why not use a Common Table Expression?? That's a SQL-standard way to achieving this - it's *not* a vendor-specific feature, and works well with many database systems.
marc_s
A: 

hi Ash,

can you share your script? i need to write a script similar to yours but i have no idea how to do it..:(

Thanks bee