Select parent row and its children and grand children - sql-server

I have a table of comments and I am trying to accomplish being able to select the root comments (`ParentCommentId = 0) and then out of the parent comments I got back, also select me all of the children and those children's children and so on
For example, I would get back the row for CommentId = 1038. I would also want its child (CommentId = 1039) because the ParentCommentId = 1038, and then also CommentId = 1040 because it's ParentCommentId = 1039 and etc..
I tried the below query as I think I am on the right direction.
SELECT *
FROM
(SELECT
c.CommentId,
c.PostId,
c.Comment,
c.ParentCommentId,
c.CommentDateTime
FROM
[gallery].[Comments] c
INNER JOIN
[player].[Players] p ON p.UserId = c.UserId
WHERE
c.PostId = 32
AND ParentCommentId = 0) AS ParentComments
JOIN
(SELECT
c.CommentId,
c.PostId,
c.Comment,
c.ParentCommentId,
c.CommentDateTime
FROM
[gallery].[Comments] c
INNER JOIN
[player].[Players] p ON p.UserId = c.UserId
WHERE
c.PostId = 32
AND ParentCommentId != 0) AS ChildComments ON ParentComments.CommentId = ChildComments.ParentCommentId
But I am getting back wrong data for sure, like the child on same row as parent, ideally I would like the children to be separate rows. It also only goes 1 child deep and am definitely missing a lot of comments (there are way more than the 5 pictured below). I seem to only be getting a root comment and it's first child and not any that don't have children or the root comments grand children.

You're likely missing data because you used an inner join. This is problematic for cases where the grand-parent isn't in the table, e.g.:
for CommentID = 1036 we are not given the grand-parent/parent in the data extract
for any comment at level 1 of the hierarchy (i.e. Parent = 0)
Using a left join should fix this.
Data used
declare #target table (
CommentID int
,PostID int
,Comment varchar(200)
,ParentCommentId int
);
insert into #target
values
(1036, 32, 'Que?', 1033)
,(1037, 32, 'What up mane', 1035)
,(1038, 32, 'Hi', 0)
,(1039, 32, 'Can you see me?', 1038)
,(1040, 32, 'Test', 1039)
,(1041, 32, 'T', 1038)
,(1042, 32, 'Yoooo', 0)
,(1043, 32, 'Test?', 1042)
,(1044, 32, 'Test 1', 1039)
,(1045, 32, 'Test 2', 1039)
;
Getting the Hierarchy
A simple hierarchy table can be built showing the three levels of
select
GrandParentCommentID = isnull(b.ParentCommentID, 0)
,a.ParentCommentID
,a.CommentID
from #target as a
left join #target as b on a.ParentCommentId = b.CommentID
Full Answer
with Hierarchy as (
select
GrandParentCommentID = b.CommentID
,a.ParentCommentID
,a.CommentID
from #target as a
inner join #target as b on a.ParentCommentId = b.CommentID
)
select
hier.GrandParentCommentID
,hier.ParentCommentID
,hier.CommentID
,details.Comment
from Hierarchy as hier
inner join #target as details on details.CommentID = hier.CommentID
order by
hier.GrandParentCommentID
,hier.ParentCommentID
Results
Bonus
If you want to get the level as a column, you can use a recursive CTE as below (I'm sure there's better ways):
;with Hierarchy as (
select
GrandParentCommentID = 0
,ParentCommentID = 0
,CommentID
,hier_level = 1
from #target where ParentCommentID = 0
union all
select
GrandParentCommentID = h.ParentCommentID
,t.ParentCommentID
,t.CommentID
,hierarchy_level = h.hier_level + 1
from Hierarchy as h
inner join #target as t on t.ParentCommentId = h.CommentID
)
select * from Hierarchy
Add a grand-grand-child for demonstration:
insert into #target values (1045, 32, 'Test 2', 1039);
Results:

Related

Query works as expected, SSRS finds error?

This question was closed because someone thought it was the same issue as SSRS multi-value parameter using a stored procedure
But it is not. My report is not a stored procedure and thus, behaves differently. Also, this issue describes a result of getting no results if multi-valued params are used and that too is inaccurate for this scenario. So I'll try posting this again.
My report for the most part works. It is when I select more than one value from either of 2 specific params (#global, #manual) that I get this error:
Here is the SQL:
DECLARE #STATE VARCHAR(2) = 'mn'
,#START DATE = '6/1/2020'
,#END DATE = '7/1/2020'
,#GLOBAL VARCHAR(50) = 'indigent fee'
,#MANUAL VARCHAR(100) = '''misc charges'',''discount'''
DROP TABLE
IF EXISTS #customers
,#test
SELECT DISTINCT ch.amount
,ch.vehicle_program_id
,c.customer_id
,ch.customer_charge_id
,ch.charge_type
INTO #customers
FROM customer c
JOIN customer_charge ch(NOLOCK) ON c.customer_id = ch.customer_id
JOIN service_history sh(NOLOCK) ON sh.customer_id = c.customer_id
JOIN header h(NOLOCK) ON h.service_history_id = sh.service_history_id
WHERE ch.entry_date BETWEEN #START
AND #END
AND ch.price_trigger_id IN (
16
,15
)
AND ch.source_type = 1
AND sh.service_type = 5
AND h.is_duplicate = 0;
WITH CTE_global
AS (
SELECT DISTINCT ch.charge_type
,'global' AS type
FROM customer_charge ch
JOIN store s ON ch.store_id = s.store_id
JOIN address a ON a.id = s.address_id
JOIN locality l ON a.locality_id = l.id
WHERE l.region = #state
AND ch.price_trigger_id = 16
UNION ALL
SELECT 'None'
,'global'
)
,CTE_manual
AS (
SELECT DISTINCT ch.charge_type
,'manual' AS type
FROM customer_charge ch
JOIN store s ON ch.store_id = s.store_id
JOIN address a ON a.id = s.address_id
JOIN locality l ON a.locality_id = l.id
WHERE l.region = #state
AND ch.price_trigger_id = 15
UNION ALL
SELECT 'None'
,'manual'
)
SELECT DISTINCT c.last_name
,c.first_name
,vp.account_no
,cust.charge_type
,cust.amount
,sh.service_date
,s.store_name_short
,GLOBAL = g.charge_type
,manual = m.charge_type
INTO #test
FROM vehicle_program vp(NOLOCK)
JOIN vehicle v(NOLOCK) ON v.vehicle_id = vp.vehicle_id
JOIN service_history sh(NOLOCK) ON sh.vehicle_program_id = vp.program_id
AND service_type = 5
JOIN customer c(NOLOCK) ON v.customer_id = c.customer_id
AND c.customer_id = sh.customer_id
JOIN store s(NOLOCK) ON vp.current_store_id = s.store_id
JOIN #customers cust ON cust.customer_id = c.customer_id
AND cust.vehicle_program_id = sh.vehicle_program_id
JOIN customer_condition cc(NOLOCK) ON c.customer_id = cc.customer_id
JOIN customer_charge ch(NOLOCK) ON ch.customer_id = c.customer_id
JOIN service_charge sc ON sc.service_history_id = sh.service_history_id
AND sc.customer_charge_id = cust.customer_charge_id
JOIN header h(NOLOCK) ON h.service_history_id = sh.service_history_id
JOIN CTE_global g ON g.charge_type = ch.charge_type
JOIN CTE_manual m ON m.charge_type = ch.charge_type
WHERE cc.state_of_conviction = #state
AND sh.service_date BETWEEN #START
AND #END
AND h.is_duplicate = 0
SELECT *
FROM #test
WHERE GLOBAL IN (
CASE
WHEN #global IN ('None')
THEN charge_type
WHEN #global NOT IN ('None')
THEN #global
END
)
OR manual IN (
CASE
WHEN #manual IN ('None')
THEN charge_type
WHEN #manual NOT IN ('None')
THEN #manual
END
)
For clarity, the last bit in the query there is some logic to allow for these two params to be optional: so by selecting 'None' that param is rendered useless basically. It seems clear that the issue is with this last bit, specifically my WHERE clause using the CASE expression. When I remove that, I don't get the error, but I of course lose my logic. What's most confusing is that the error indicates an issue with a comma, but there's no comma in that part of the SQL?? Any help is going to be greatly appreciated.
Assuming users will only select 'None' from the list on it's own and never with another value then the following should work.
WHERE (GLOBAL IN (#Global) OR #Global = 'None')
AND
(manual IN (#manual) OR #manual = 'None')
this question was closed because someone thought it was the same issue
It is a dupe, but you kind of have to read between the lines in the other answers to apply it to this scenario. The point is that SSRS replaces multi-select parameters with delimited strings in the query body itself, and this transformation can lead either to unexpectedly getting no results, or in an illegal SQL query, depending on where the parameter marker appears in the original query.
I'll make it a bit clearer exactly what's going on. You can repro this behavior with this as your Data Set query:
drop table if exists #foo
create table #foo(charge_type varchar(200) , global varchar(200))
select *
from #foo
WHERE GLOBAL IN (
CASE
WHEN #global IN ('None')
THEN charge_type
WHEN #global NOT IN ('None')
THEN #global
END
)
And configure #global as a parameter that allows multi-select. When the user selects multiple values SSRS transforms the query into:
drop table if exists #foo
create table #foo(charge_type varchar(200) , global varchar(200))
select *
from #foo
WHERE GLOBAL IN (
CASE
WHEN N'a',N'b' IN ('None')
THEN charge_type
WHEN N'a',N'b' NOT IN ('None')
THEN N'a',N'b'
END
)
Which fails with An expression of non-boolean type specified in a context where a condition is expected, near ','.

T-SQL - Update Table with data from the same table - Ambiguous table

I'm having trouble understanding why this query is not working. I get a message
The table '#PriceChanges' is ambiguous
The first mention of #PriceChanges is underlined
UPDATE #PriceChanges
SET MaxQty = MIN(ISNULL(PT.MinQty, 100000000))
FROM #PriceChanges P
LEFT JOIN #PriceChanges PT ON P.ChangeType = PT.ChangeType
AND P.ItemNo = PT.ItemNo
AND P.MinQty < PT.MinQty
So what I'm trying to achieve is setting the MAX quantity of a given line to the next MIN quantity found in the same table. If there's none found, then just make it a ridiculously high number (100,000,000)
The end result should look like something like this
MinQty MaxQty
-----------------
0 20
20 50
50 100
100 100000000
The ambiguity arises because the FROM clause of the UPDATE refers to the #PriceChanges table twice, so there is no way for SQL Server to know which of the two you intend to update. To resolve the ambiguity, instead of writing UPDATE #PriceChanges, use UPDATE P or UPDATE PT. Here's a trivial example:
create table #Test (id int, datum char(1));
insert #Test values (1, ' '), (2, ' ');
-- ERROR: The table '#Test' is ambiguous.
update #Test set datum = 'X' from #Test T1 inner join #Test T2 on T1.id = T2.id + 1;
-- CORRECT: Use the appropriate table alias to indicate which instance of #Test you want to update.
update T1 set datum = 'X' from #Test T1 inner join #Test T2 on T1.id = T2.id + 1;
Creating an intermediary table worked, I still wonder why this couldn't all be put into a single update
SELECT P.ChangeType, P.ItemNo, P.MinQty, MIN(PT.MinQty) AS MaxQty
INTO #MaxQty
FROM #PriceChanges P
LEFT JOIN #PriceChanges PT
ON P.ChangeType = PT.ChangeType
AND P.ItemNo = PT.ItemNo
AND P.MinQty < PT.MinQty
GROUP BY P.ChangeType, P.ItemNo, P.MinQty
UPDATE #PriceChanges
SET MaxQty = ISNULL(PM.MaxQty, 100000000)
FROM #PriceChanges P
LEFT JOIN #MaxQty PM
ON P.ChangeType = PM.ChangeType
AND P.ItemNo = PM.ItemNo
AND P.MinQty = PM.MinQty
I see no use for ISNULL(PT.MinQty, 100000000). MIN() ignores NULL values. And you don't need a self join. An updatable CTE or subquery works:
UPDATE pc
SET MaxQty = min_minqty
FROM (SELECT pc.*, MIN(pc.MinQty) OVER (PARTITION BY ItemNo, ChangeType) as min_minqty
FROM #PriceChanges pc
) pc
WHERE pc.MaxQty <> min_minqty;
EDIT:
You appear to want:
with pc as (
select pc.*,
lead(pc.MinQty) over (order by pc.MinQty) as next_MinQty
from #PriceChanges pc
)
update pc
set MaxQty = next_MinQty;

Fill Fact Table with MultiColumn Business Key Lookup

I've been doing some searching on Stack Overflow as well as Google and haven't quite found the answer to my question, so here we go:
It's been a minute since I've done a 'from the ground up' data warehouse project, so I'm dusting off some of my past knowledge, but am blanking on a solution to one of my data load scenarios.
I am creating a Fact Table (factOrderLines) with of course many dimensions joined to it. One of the dimensions I would like to link to factOrderLines is the dimItem. The problem is an Item is unique based on either the item's vendor and vendor part number, manufacturer and manufacturer part number, or an identifier from a subset of items called ManagedItems (MngItemID).
source ex:
Vendor VendorPartNo Manufacturer ManufacturerPartNo MngItemID
100 3456 NULL NULL 67
100 3254 03 1234 23
NULL NULL 03 1235 24
NULL NULL 15 5120 NULL
Problem is when I do my join to the dimItem table from my source table to populate the factOrderLines table I have three lookup scenarios. This is causing the numbers to inflate and performance to be horrible.
LEFT OUTER JOIN dimItem AS i ON
(i.Vendor = src.Vendor AND i.VendorPartNo = src.VndrItemID) OR
(i.Manufacturer = src.Manufacturer AND
(i.ManufacturerPartNo = src.MfgItemID) OR (i.MngItemID = src.MngItemID)
Is there a more efficient/better approach to this scenario than what I have started to implement?
edit: Full INSERT query (for better understanding)
INSERT INTO fctOrderLine
(PurchaseOrderKey
,DateKey
,PurchaseOrderLineNo
,VendorKey
,ManufacturerKey
,ItemKey
,UnitPrice
,Qty
,UnitOfMeasure
,LineTotal)
SELECT PurchaseOrderKey = po.PurchaseOrderKey
,DateKey = ISNULL(c.DateKey, 19000101)
,PurchaseOrderLineNo = ISNULL(p.POLineNbr, -1)
,VendorKey = ISNULL(v.VendorKey, -1)
,ManufacturerKey = ISNULL(m.ManufacturerKey, -1)
,ItemKey = ISNULL(i.ItemKey, -1)
,UnitPrice = ISNULL(p.UnitPrice, -1.00)
,Qty = ISNULL(p.POQty, -1.00)
,UnitOfMeasure = ISNULL(p.ANSI_UOM, N'UNKNOWN')
,LineTotal = ISNULL(p.LineTotalCost, -1)
FROM stgOrders AS p
INNER JOIN dimPurchaseOrder AS po ON po.OrderNo = p.PONumber
LEFT OUTER JOIN dimCalendar AS c ON c.Date = (CASE WHEN p.DT_PO IS NULL OR ISDATE(REPLACE(p.DT_PO, '''', '')) = 0 THEN CAST('19000101' AS DATETIME) ELSE REPLACE(p.DT_PO, '''', '') END)
LEFT OUTER JOIN dimVendor AS v ON v.VendorID = p.VendorID
LEFT OUTER JOIN dimManufacturer AS m ON m.ManufacturerID = p.MfgID
LEFT OUTER JOIN dimItem AS i ON (i.VendorKey = v.VendorKey AND i.VendorPartNo = p.VndrItemID) OR (i.ManufacturerKey = m.ManufacturerKey AND i.ManufacturerPartNo = p.MfgItemID) OR (i.MngItemID = p.MngItemID)

SQL Server CTE hierarchy keyword search

I've run into a tricky issue with recursive searching in an eCommerce shop stored procedure. Basically this single procedure will return all products factoring in basic filters and paging, and using a parent/child category table to perform recursive checks down the hierarchy. This is works beautifully and the CTE's run extremely fast, however the recent addition of a keyword search which needs to search across the Category Name, Product Name, and Style Number has caused dramas.
This seemed quite trivial at first as the 1st CTE already generates a table of all relevant categories in the hierarchy based on the supplied #categoryid and then joins onto the rest of the Product specific tables for all filtering. The Product Name and Style Number search works fine, but I cannot for the life of me get a Category Name search to work because it needs to search the category tree for any matches down the hierarchy tree starting from the top.
EDIT: I'm now thinking it may just be a lot easier to add a "tag" table against Products which stores all keyword related tags such as category name, product name and style etc and search directly against the tags.
For example a subset of the Category hierarchy looks like this:
Mens
- Polos
- Jerseys
- Pants
Womens
- Pants
- Shirts
- Polos
Supporters
- State Of Origin
- Mens
- Womens
- Kids
- Bulldogs
- Jerserys
- Pants
- Shirts
- Caps
- Warratahs
In my sample code below i am passing a search term of "origin mens" which should return all products within the "State of Origin" category that are also within the "Mens" category. The only thing it matches on is Product Names that start with "Origin" and nothing else because the category at the product level is not "State of Origin" as this is the parent. Any help here would be fantastic!
-- Variable Declarations
DECLARE #categoryid int
DECLARE #minprice int
DECLARE #maxprice int
DECLARE #sizefilter int
DECLARE #colourfilter int
DECLARE #searchstring varchar(255)
DECLARE #totalrows int
-- Variables values for testing
SET #categoryid = 0
SET #minprice = 0
SET #maxprice = 0
SET #sizefilter = 0
SET #colourfilter = 0
SET #searchstring = 'origin mens'
-- Setup paging table
DECLARE #indextable table (rownum int identity(1,1), recordid int);
BEGIN
-- First run CTE recursively over all categories in hierarchy
;WITH categoryCTE AS (
SELECT cat.id as CategoryId, cat.name as CategoryName
FROM dbo.shopcategory AS cat
WHERE (#categoryid = 0 OR cat.id = #categoryid)
AND cat.isenabled = 1
UNION ALL
SELECT child.id as CategoryId, child.name as CategoryName
FROM dbo.ShopCategory AS child
INNER JOIN categoryCTE AS parent
ON child.parentid = parent.CategoryId
WHERE child.isenabled = 1
),
-- Now join CTE onto products tables via linker product_shopcategory
productsCTE AS (
SELECT p.id, ppc.shopcategoryid, ppc.listorder as catlistorder
FROM categoryCTE as cat
INNER JOIN product_shopcategory ppc ON ppc.shopcategoryid = cat.CategoryId
INNER JOIN product p ON ppc.productid = p.id
INNER JOIN productlocality pl ON pl.productid = p.id
-- ** SEARCH - Join List to Table function of keywords
INNER JOIN dbo.udf_parseList(#searchString, ' ') s
ON (cat.CategoryName + p.Name + p.stylenumber LIKE '%' + s.array_Value + '%')
LEFT JOIN product_quantity pq ON pq.productid = p.id AND pq.localityid = #localityid
LEFT JOIN productcolour pc ON pc.productid = p.id
LEFT JOIN productcolourswatch pcs ON pc.productcolourswatchid = pcs.id
LEFT JOIN product_productsize pps ON pps.productid = p.id
LEFT JOIN productsize ps ON pps.productsizeid = ps.id
WHERE p.isenabled = 1
AND pq.quantity > 1
AND (pc.isenabled IS NULL OR pc.isenabled = 1)
AND (#minprice = 0 OR pl.price >= #minprice)
AND (#maxprice = 0 OR pl.price <= #maxprice)
-- Colour Group Filters
AND (#colourfilter = 0
OR
(pcs.swatchgroupid = #colourfilter AND (pq.productcolourid = pc.id AND pq.quantity > 0))
)
-- Size Group Filters
AND (#sizefilter = 0
OR
(ps.sizegroupid = #sizefilter AND (pq.productsizeid = pps.productsizeid AND pq.quantity > 0))
)
)
-- Create Paging table of results and strip out duplicates with group by
INSERT INTO #indextable (recordid)
SELECT DISTINCT id
FROM productsCTE
GROUP BY id
ORDER BY id;
Finally solved it! I almost went down the path of creating a full tag table structure so that i could search directly against keyword tags rather than the direct data, however in trying to script a product tags table containing a nesting of the category hierarchy I found the solution which was quite simple.
In the solution procedure below i've created a new column in the CategoryCTE to hold a comma delimited list of category names that is built recursively and this then tracks the full tree for the supplied CategoryId. Now that i have a comma delimited list of Category names, I can then factor this into my 2nd CTE and perform a standard LIKE clause factoring in Product Name, Style Number, and Category Names. Finally in order to make this search a little smarter i made the keyword search inclusive of all keywords so that "mens origin" will only return products matching both of these keywords as oppose to any matches, and this was done using the NOT EXISTS clause.
Hope this helps someone else it performs very fast as well!
-- Variable Declarations
DECLARE #categoryid int
DECLARE #minprice int
DECLARE #maxprice int
DECLARE #sizefilter int
DECLARE #colourfilter int
DECLARE #searchstring varchar(255)
DECLARE #totalrows int
-- Variables values for testing
SET #categoryid = 0
SET #minprice = 0
SET #maxprice = 0
SET #sizefilter = 0
SET #colourfilter = 0
SET #searchstring = 'origin mens'
-- Setup paging table
DECLARE #indextable table (rownum int identity(1,1), recordid int);
BEGIN
-- First run CTE recursively over all categories in hierarchy inclusive of supplied categoryId
;WITH categoryCTE AS (
SELECT cat.id as CategoryId, cat.name as CategoryName,
CONVERT(varchar(255),cat.name) AS Tags
FROM dbo.shopcategory AS cat
WHERE (#categoryid = 0 OR cat.id = #categoryid)
AND cat.isenabled = 1
UNION ALL
SELECT child.id as CategoryId, child.name as CategoryName, CONVERT(varchar(255),
parent.Tags + CONVERT(varchar(32),',' + child.name)) AS Tags
FROM dbo.ShopCategory AS child
INNER JOIN categoryCTE AS parent
ON child.parentid = parent.CategoryId
WHERE child.isenabled = 1
),
-- Now join CTE onto products tables via linker product_shopcategory
productsCTE AS (
SELECT p.id, ppc.shopcategoryid, ppc.listorder as catlistorder
FROM categoryCTE as cat
INNER JOIN product_shopcategory ppc ON ppc.shopcategoryid = cat.CategoryId
INNER JOIN product p ON ppc.productid = p.id
INNER JOIN productlocality pl ON pl.productid = p.id
LEFT JOIN product_quantity pq ON pq.productid = p.id AND pq.localityid = #localityid
LEFT JOIN productcolour pc ON pc.productid = p.id
LEFT JOIN productcolourswatch pcs ON pc.productcolourswatchid = pcs.id
LEFT JOIN product_productsize pps ON pps.productid = p.id
LEFT JOIN productsize ps ON pps.productsizeid = ps.id
WHERE p.isenabled = 1
AND pq.quantity > 1
AND (pc.isenabled IS NULL OR pc.isenabled = 1)
AND pl.localityid = #localityid
AND (#minprice = 0 OR pl.price >= #minprice)
AND (#maxprice = 0 OR pl.price <= #maxprice)
-- Keyword Search filter
AND (#searchstring = '' OR NOT EXISTS
(
SELECT NULL
FROM dbo.udf_parseList(#searchString, ' ')
WHERE cat.Tags + p.Name + p.stylenumber + pc.stylenumber NOT LIKE '%' + array_Value + '%'
)
)
-- Colour Group Filters
AND (#colourfilter = 0
OR
(pcs.swatchgroupid = #colourfilter AND (pq.productcolourid = pc.id AND pq.quantity > 0))
)
-- Size Group Filters
AND (#sizefilter = 0
OR
(ps.sizegroupid = #sizefilter AND (pq.productsizeid = pps.productsizeid AND pq.quantity > 0))
)
)
-- Create Paging table of results and strip out duplicates with group by
INSERT INTO #indextable (recordid)
SELECT DISTINCT id
FROM productsCTE
GROUP BY id
ORDER BY id;

TSQL - While loop within select?

In SQL server
Ok, so I'm working with a database table in which rows can have parent rows, which can then have parent rows of their own. I need to select the root 'row'. I don't know the best way to do this.
There is a field called ParentId, which links the row to the row with that ID. When the ParentId = 0, it is the root row.
This is my query now:
SELECT Releases.Name,WorkLog.WorkLogId
FROM WorkLog,Releases
WHERE
Releases.ReleaseId = WorkLog.ReleaseId
and WorkLogDateTime >= #StartDate
and WorkLogDateTime <= #end
I don't really need the Release Name of the child releases, I want only the root Release Name, so I want to select the result of a While loop like this:
WHILE (ParentReleaseId != 0)
BEGIN
#ReleaseId = ParentReleaseId
END
Select Release.Name
where Release.RealeaseId = #ReleaseId
I know that syntax is horrible, but hopefully I'm giving you an idea of what I'm trying to acheive.
Here is an example, which could be usefull:
This query is getting a lower element of a tree, and searching up to the parent of parents.
Like I have 4 level in my table -> category 7->5, 5->3, 3-> 1. If i give it to the 5 it will find the 1, because this is the top level of the three.
(Changing the last select you can have all of the parents up on the way.)
DECLARE #ID int
SET #ID = 5;
WITH CTE_Table_1
(
ID,
Name,
ParentID
)
AS(
SELECT
ID,
Name,
ParentID
FROM Table_1
WHERE ID = #ID
UNION ALL
SELECT
T.ID,
T.Name,
T.ParentID
FROM Table_1 T
INNER JOIN CTE_Table_1 ON CTE_Table_1.ParentID = T.ID
)
SELECT * FROM CTE_Table_1 WHERE ParentID = 0
something like this
with cte as
(
select id,parent_id from t where t.id=#myStartingValue
union all
select t.id,t.parent_id
from cte
join t on cte.parent_id = t.id where cte.parent_id<>0
)
select *
from cte
join t on cte.id=t.id where cte.parent_id = 0
and with fiddle : http://sqlfiddle.com/#!3/a5fa1/1/0
Using Andras approach, I edited the final select to directly give me the ID of the root release
WITH cte_Releases
(
ReleaseId,
ParentReleaseID
)
AS(
SELECT
ReleaseId,
ParentReleaseID
FROM Releases
Where ReleaseId = 905
UNION ALL
SELECT
R.ReleaseId,
R.ParentReleaseID
FROM Releases R
INNER JOIN cte_Releases ON cte_Releases.ParentReleaseID = R.ReleaseId
)
SELECT max(ReleaseId) as ReleaseId, min(ReleaseId) as RootReleaseId FROM cte_Releases
My problem now is I want to run through all #IDs (905 in that code) and join each record to a result

Resources