Create Hierarchical Tree from 2 Columns in SQL - sql-server

I am having a large set of data in 2 columns where I need to create hierarchical structure from it.
Below is the input table structure.
Parent
Child
P4S/JJ
P4S/JJ/00/AMS
P4S/JJ
P4S/JJ/SIM
P4S/JJ/00
P4S/JJ/00/ALMS
P4S/JJ/00
P4S/JJ/00/CNT VQ/FW-LL-01
P4S/JJ/00
P4S/JJ/00/CNT VQ/FW-LL-02
P4S/JJ/00
P4S/JJ/00/QQ
P4S/JJ/00
P4S/JJ/00/QQMQ
P4S/JJ/00
P4S/JJ/00/FGS
P4S/JJ/00
P4S/JJ/00/IAMS
P4S/JJ/00
P4S/JJ/00/ICS-SA
Requirement is to find all the Child of Parent. But the issue here is Parent can also be a child of another Parent in the same column.
I was trying with below query and nowhere near to creating a hierarchical structure.
Query tried:
with cteP as (
select Parent,Child
from [dbo].[Data]
where Parent is not null
Union All
Select r.Parent,r.Child
From [dbo].[Data] r
inner join cteP on r.Parent = cteP.Parent
Select *
From cteP A
--Order By A.Parent
option (maxrecursion 0)
I tried using hierarchy id and getting the error "Implicit conversion
from data type hierarchyid to varchar is not allowed. Use the CONVERT
function to run this query."
I want my output table in below format until the child is null:
Parent
Child
Sub Child1
P4S/JJ
P4S/JJ/00/AMS
P4S/JJ
P4S/JJ/SIM
P4S/JJ/SIM/MMFOD01
P4S/JJ
P4S/JJ/SIM
P4S/JJ/SIM/MMSCP01
P4S/JJ
P4S/JJ/SIM
P4S/JJ/SIM/MMSIM01
P4S/JJ
P4S/JJ/SIM
P4S/JJ/SIM/UAW000
P4S/JJ
P4S/JJ/SIM
P4S/JJ/SIM/UWP001
P4S/JJ
P4S/JJ/SIM
P4S/JJ/SIM/UWP002

Related

How use recursive CTE content for specific child node?

I have a recursive CTE query in SQL Server which handles getting the depth of each parent and child values. However I want to get the full depth for only on specific child. For example the data I have looks something like this, I only want to get the results for where c_key is equal to child my initial query below the table gets the results for all links.
I tried to add a where clause in to the unioned select statement, but this just returned the the 0th depth rows.
c_key
p_key
child
teen
teen
adult
adult
old
young
middle
middle
old
WITH cte_data (c_key, p_key, depth) AS
(
SELECT c_key, p_key, 0 AS depth
FROM my_table
WHERE p_key = 'old'
UNION ALL
SELECT c.c_key, c.p_key, o.depth + 1 AS depth
FROM cte_data o
INNER JOIN my_table c ON o.c_key = c.p_key
)
SELECT *
FROM cte_data
Seemingly, you should swap columns for the join condition and change the where search condition according to your task condition.
WITH cte_data (c_key, p_key, depth) AS
(
SELECT c_key, p_key, 0 AS depth
FROM my_table
WHERE c_key = 'child'
UNION ALL
SELECT c.c_key, c.p_key, o.depth + 1 AS depth
FROM cte_data o
INNER JOIN my_table c ON o.p_key = c.c_key
)
SELECT *
FROM cte_data
ORDER by depth

Need to take price of parent to child item when child item do not have price

I'm trying to import item price from my database. And for some item only parent item has price and child is not exist in tarif table, in that case I tried to take the price from parent to child. And for some item even parent don't have price, in that case in my export in price field "NULL" is there.
My Query:
GA_ARTICLE is the item code, which the reference for my item and tarif table,GA_CODEARTICLE is same for both CHILD and PARENT item, GF_DEVISE is the field where my currency code is stored,
SELECT ga_article,
CASE
WHEN ga_article LIKE ga_Codearticle + '%X' THEN
SELECT TOP(1) GF_PRIXUNITAIRE
FROM tarif WHERE GF_ARTICLE LIKE ga_Codearticle + '%' AND GF_DEVISE='QAR')
END
price
FROM Article
LEFT JOIN tarif
ON gf_article = GA_ARTICLE
AND GF_DEVISE = 'QAR'
You need to fix up your LEFT JOIN to already SELECT that TOP 1 record, and then use the CASE statement to decide which field to display for price.
SELECT ga_article,
CASE
WHEN ga_article LIKE ga_Codearticle + '%X' THEN
t.GF_PRIXUNITAIRE
WHEN otherCondition THEN otherField
ELSE NULL --this is implied even if you leave it out
END
price
FROM Article
LEFT JOIN
(SELECT TOP 1 *
FROM tarif
WHERE gf_article = GA_ARTICLE
AND GF_DEVISE = 'QAR') t

I have Child,Mother M:M Table.How to select Child with all common Mother their has?

I have 3 table with Mother, Child, and Junction like this
Mother
Child (ChildName ZZZ Should Have 53 Code)
Junction
I want to use Mother (at least 2) as Where Condition to know what child their has in common
like
Select CodeChild
From Junction
Where CodeMother in ('02','03')
What I expect to result
Can't test this
Select Junction.CodeChild, Child.ChildName From Junction
Inner Join Child On Junction.ChildCode = Child.CodeChild
Where Junction.CodeMother = CodeMother
As per OP Edit
Solved but appreciate any better ways
Since Mother condition can have 1-4 the query depends on that
For Example
Select r.ChildName
From (Select j.CodeChild From Junct j Where j.CodeMother = 2)M1
inner join (Select j.CodeChild From Junct j Where j.CodeMother = 3)M2 On
M2.CodeChild = M1.CodeChild
//If More Mother Condition Just put inner join M3,M4 and So on Here
inner join Child r on M1.CodeChild = r.CodeChild

Returning the correct xml structure from query in SQL Server

I'm trying to select data from a consumer parent table and inner join on multiple child tables and return it as XML.
I have the Consumer parent table and 2 child tables ConsumerPhone and Consumer Address.
The Output I want should look like this
<Consumer Username="eallen">
<ConsumerPhone/>
<ConsumerAddress />
</Consumer>
<Consumer Username="jgibson">
<ConsumerPhone/>
<ConsumerAddress />
</Consumer>
But my query (which I think is the issue) is placing the Consumer Address inside the ConsumerPhone element
<Consumer Username="eallen">
<ConsumerPhone>
<ConsumerAddress />
</ConsumerPhone>
</Consumer>
<Consumer Username="jgibson">
<ConsumerPhone>
<ConsumerAddress />
</ConsumerPhone>
</Consumer>
Here is the query
SELECT Consumer.Username,ConsumerPhone.Number,ConsumerAddress.Country
FROM [dbo].[Consumer] Consumer
LEFT JOIN [dbo].[ConsumerPhone] ConsumerPhone
ON Consumer.ConsumerID = ConsumerPhone.ConsumerID
LEFT JOIN [dbo].[ConsumerAddress] ConsumerAddress
ON Consumer.ConsumerID = ConsumerAddress.ConsumerID
order by Consumer.ConsumerID asc
OFFSET 100 ROWS
FETCH NEXT 100 ROWS ONLY
FOR XML AUTO;
I'm not sure how to fix my query to get the output I'm looking for.
Thanks
I changed it to use nested FOR XML Statements to allow for multiple values in the correct element.
SELECT
Consumer.*,
(SELECT
cp.*
FROM dbo.ConsumerPhone cp
WHERE cp.ConsumerID = Consumer.ConsumerID
FOR XML PATH('ConsumerPhone'), TYPE
) AS 'ConsumerPhoneNos'
FROM dbo.Consumer Consumer
where Consumer.ConsumerID = 220901
FOR XML PATH('Consumer'), ROOT('Consumers')
This will work:
SELECT Consumer.Username AS "#Username",
ConsumerPhone.Number AS "ConsumerPhone",
ConsumerAddress.Country AS "ConsumerAddress"
FROM [dbo].[Consumer] Consumer
LEFT JOIN [dbo].[ConsumerPhone] ConsumerPhone
ON Consumer.ConsumerID = ConsumerPhone.ConsumerID
LEFT JOIN [dbo].[ConsumerAddress] ConsumerAddress
ON Consumer.ConsumerID = ConsumerAddress.ConsumerID
order by Consumer.ConsumerID asc
OFFSET 100 ROWS
FETCH NEXT 100 ROWS ONLY
FOR XML PATH ('Consumer');

how do i get hierarchy of data from two different tables?

I have two tables TwitterStatus and twitterstatusDetails,
I have data respectively in following manner.
Here as given in twitterstatus table 4th record with the ts_StatusID "587573444633427968" is parent of twitterstatus_Details table 3rd record, which having td_inReplyTostatusID value is "587573444633427968", for next record td_StatusID of recent child record is parent of twitterstatus table having that child ts_StatusID value in ts_InreplytoStatusID field, so like that it is the hierarchy, so
how can I get the records from both the tables based on child parent relationship?
still any concern then please ask in comment.
Thank you.
I think what you are looking for is recursive CTE to get every nested level.
Hope this get you closer to your goal.
--REPLACE #TwitterStatus and #twitterstatus_Details with your tablename.
;WITH CteTStatus
AS
(
SELECT h.*, d.*, 0 as lvl
FROM #TwitterStatus AS h
INNER JOIN #twitterstatus_Details AS d ON h.id_StatusID = d.td_InreplytoStatusID
WHERE ts_StatusID = '587573444633427968'--WHERE CLAUSE TO GET ROOT PARENT
UNION ALL -- UNION TO DIG INTO CHILD's
SELECT h.*, d.*, lvl + 1 as lvl
FROM #TwitterStatus AS h
INNER JOIN #twitterstatus_Details AS d ON h.id_StatusID = d.td_InreplytoStatusID
INNER JOIN CteTStatus AS Parent ON h.ts_InreplytoStatusID = Parent.td_StatusID
)
SELECT *
FROM CteTStatus

Resources