So I have written a query to get the cumulative sum of children but I think partition sum has error as its totalling for the parent that is not part of the children.
My fiddle is http://sqlfiddle.com/#!15/88828/1
I have dont a running total but thats wrong. I want the siblings total to a child and child total back to its parent.So basically cumulative total of a child up the tree.
expected output
parent_child_tree id name dimensionvalueid level order_sequence volume cummulative_total
A1 1 A1 (null) 0 1 20 840
-----A1:1 2 A1:1 1 1 1_1 (null) 820
----------A1:1:1 3 A1:1:1 2 2 1_1_2 20 820
-----------A1:1:1:1 4 A1:1:1:1 3 3 1_1_2_3 300 800
-----------A1:1:1:2 5 A1:1:1:2. 3 3 1_1_2_3 500 500
B1 6 B1 (null) 0 6 200 300
-----B1:2 8 B1:2 6 1 6_6 (null) null
-----B1:1 7 B1:1 6 1 6_6 (null) 100
----------B1:2:1 9 B1:2:1 8 2 6_6_8 100 100
To get totals for tree nodes you need to generate hierarchy tree for every node in a subquery like this
SELECT
d.*,
v.volume,
(
WITH RECURSIVE cte AS (
SELECT
dd.id AS branch_id,
dd.id
FROM dimensionvalue dd
WHERE dd.id = d.id
UNION ALL
SELECT
cte.branch_id,
dd.id
FROM dimensionvalue dd
JOIN cte ON dd.dimensionvalueid = cte.id
)
SELECT SUM(v.volume)
FROM cte
JOIN valuation v ON v.dimensionvalueid = cte.id
GROUP BY cte.branch_id
) AS totals
FROM dimensionvalue d
LEFT JOIN valuation v ON v.dimensionvalueid = d.id
ORDER BY d.name;
If you really need all those "decoration" columns that you generate in your query for each tree node than you can combine your recursive CTE hierarchy with subquery for totals calculation like this
WITH RECURSIVE hierarchy AS (
SELECT
d.id,
d.name,
d.dimensionvalueid,
0 AS level,
CAST(d.id AS varchar(50)) AS order_sequence
FROM dimensionvalue d
WHERE d.dimensionvalueid IS NULL
UNION ALL
SELECT
e.id,
e.name,
e.dimensionvalueid,
hierarchy.level + 1 AS level,
CAST(hierarchy.order_sequence || '_' || CAST(hierarchy.id AS VARCHAR(50)) AS VARCHAR(50)) AS order_sequence
FROM hierarchy
JOIN dimensionvalue e ON e.dimensionvalueid = hierarchy.id
)
SELECT
RIGHT('-----------', h.level * 5) || h.name || ' ' AS parent_child_tree,
h.*,
v.volume,
(
WITH RECURSIVE cte AS (
SELECT
dd.id AS branch_id,
dd.id
FROM dimensionvalue dd
WHERE dd.id = h.id
UNION ALL
SELECT
cte.branch_id,
dd.id
FROM dimensionvalue dd
JOIN cte ON dd.dimensionvalueid = cte.id
)
SELECT SUM(v.volume)
FROM cte
JOIN valuation v ON v.dimensionvalueid = cte.id
GROUP BY cte.branch_id
) AS totals
FROM hierarchy h
LEFT JOIN valuation v ON v.dimensionvalueid = h.id
ORDER BY h.name
You can check a working demo here
I have 2 tables Persons and Sales. In Person there is relation between child and parent, I want to compute 20 percent of parent values with the following condition
Persons
Id | ParentId | Name
1 NULL Tom
2 1 Jake
3 2 Kate
4 3 Neil
Sales
PersonId | Sale
4 500
I want to get result like this
Id | ParentId | Name | Sale
1 Null Tom 100 <-- (500*20)/100 left 400
2 1 Jake 80 <-- (400*20)/100 left 320
3 2 Kate 64 <-- (320*20)/100 left 256
4 3 Neil 256 <-- (320*80)/100
I wrote this query but it does not give appropriate result
;WITH cte_persons
AS
(
SELECT p.Id, p.ParentId, p.Name, s.Price FROM Persons AS p
INNER JOIN Sales AS s ON s.PersonId = p.Id
UNION ALL
SELECT p.Id, p.ParentId, p.Name, CAST((c.Price - (c.Price*80)/100) AS DECIMAL(6, 2)) FROM #Persons AS p
INNER JOIN cte_persons AS c ON c.ParentId = p.Id
)
SELECT * FROM cte_persons
This should be a two steps algorithm. First traverse the hierachy to get max level. Then apply the level in a reverse order.
WITH cte_persons
AS
(
SELECT 1 as level, p.Id, p.ParentId, p.Name, s.Price, p.Id AS base
FROM Persons AS p
INNER JOIN Sales AS s ON s.PersonId = p.Id
UNION ALL
SELECT level + 1, p.Id, p.ParentId, p.Name, c.Price, c.base
FROM Persons AS p
INNER JOIN cte_persons AS c ON c.ParentId = p.Id
)
SELECT Id, ParentId, Name,
CASE level WHEN 1
THEN price - sum(delta) over(partition by base order by level desc) + delta
ELSE delta END sale
FROM (
SELECT *,
(power (0.8000, max(level) over(partition by base) - level) * 0.2) * price delta
FROM cte_persons
) t
ORDER BY id;
db<>fiddle
Below are the tables:
relation table
cid
pid
101
202
566
322
875
345
people table
id
name
gender
101
Riya
F
566
Aman
M
202
Rakesh
M
875
lucky
M
202
Reena
F
322
Raina
F
345
Rohit
M
322
Mohit
M
345
Meena
F
output
Child
Mother
Father
Riya
Reena
Rakesh
Aman
Raina
Mohit
Lucky
Rohit
Meena
I tried this:
SELECT mother,
father
FROM (
SELECT id,
name,
sum(
CASE
WHEN gender = 'F' THEN 1
ELSE 0) AS mother,
sum (
CASE
WHEN gender = 'M' THEN 1
ELSE 0) AS father
FROM people
INNER JOIN relation
ON people. id = relation.p_id
GROUP BY id,
name) t1
INNER JOIN relation
ON relation.p_id = t1.id
Please let me know the query, for how to fetch this output. this above query does not work, I am not able to figure how to output child also.
You must join relation to 2 copies of people.
The 1st copy will return the child's name and the 2nd copy will return the names of the parents.
Then group by child and use conditional aggregation to get the names of the parents in one row:
SELECT c.name Child,
MAX(CASE WHEN p.gender = 'F' THEN p.name END) Mother,
MAX(CASE WHEN p.gender = 'M' THEN p.name END) Father
FROM relation r
INNER JOIN people c ON c.id = r.cid
INNER JOIN people p ON p.id = r.pid
GROUP BY r.cid, c.name;
See the demo.
You can join twice and then PIVOT:
SELECT *
FROM (
SELECT c.name AS child,
p.name AS parent,
p.gender
FROM relations r
INNER JOIN people c
ON r.cid = c.id
INNER JOIN people p
ON r.pid = p.id
)
PIVOT (
MAX(parent) FOR gender IN (
'M' AS father,
'F' AS mother
)
)
Which, for the sample data:
CREATE TABLE people (id, name, gender) AS
SELECT 101, 'Riya', 'F' FROM DUAL UNION ALL
SELECT 566, 'Aman', 'M' FROM DUAL UNION ALL
SELECT 202, 'Rakesh', 'M' FROM DUAL UNION ALL
SELECT 875, 'lucky', 'M' FROM DUAL UNION ALL
SELECT 202, 'Reena', 'F' FROM DUAL UNION ALL
SELECT 322, 'Raina', 'F' FROM DUAL UNION ALL
SELECT 345, 'Rohit', 'M' FROM DUAL UNION ALL
SELECT 322, 'Mohit', 'M' FROM DUAL UNION ALL
SELECT 345, 'Meena', 'F' FROM DUAL;
CREATE TABLE relations (cid, pid) AS
SELECT 101, 202 FROM DUAL UNION ALL
SELECT 566, 322 FROM DUAL UNION ALL
SELECT 875, 345 FROM DUAL;
Outputs:
CHILD
FATHER
MOTHER
Riya
Rakesh
Reena
Aman
Mohit
Raina
lucky
Rohit
Meena
db<>fiddle here
Try this one
with cte as
(
select name as child, r.pid as pid
from people p
join relation r
on p.id=r.cid
)
select ee.child as child,
(select name from people PM where id=ee.pid and PM.gender='F') as Mother,
(select name from people PP where id=ee.pid and PP.gender='M') as Father
from cte ee
You can try below query -
SELECT P.name Child, p2.name mother, p3.name father
FROM relation R
JOIN people P ON R.cid = P.id
JOIN people P2 ON R.pid = P.id
AND P.gender = 'F'
JOIN people P3 ON R.pid = P.id
AND P.gender = 'M'
SELECT DISTINCT P1.NAME AS CHILD,(SELECT NAME FROM PEOPLE PM WHERE ID=T.PID AND PM.GENDER='F') AS MOTHER,
(SELECT NAME FROM PEOPLE PP WHERE ID=T.PID AND PP.GENDER='M') AS FATHER FROM
(SELECT R.CID,NAME,R.PID,P.GENDER FROM PEOPLE P,RELATIONS R
WHERE P.ID=R.PID) T,PEOPLE P1
WHERE T.CID=P1.ID;
select * from
(select * from
(select p.firstname as child, (select p1.firstname from persons p1 where r.p_id=p1.id and p1.gender='M') as father
from persons p inner join relations r on
p.id=r.id
) t
where t.father is not null
) as table1
inner join
(select * from
(select p.firstname as child, (select p1.firstname from persons p1 where r.p_id=p1.id and p1.gender='F') as mother
from persons p inner join relations r on
p.id=r.id
) t
where t.mother is not null ) as table2
on table1.child=table2.child
SELECT l.cid AS id,
r.NAME AS Child,
mother.NAME AS Mother,
father.NAME AS Father
FROM testdb.dbo.people r
JOIN testdb.dbo.relation l
ON l.cid = r.id
JOIN (SELECT l.cid AS id,
r.NAME
FROM testdb.dbo.people r
JOIN testdb.dbo.relation l
ON l.pid = r.id
AND gender = 'F') AS mother
ON l.cid = mother.id
JOIN (SELECT l.cid AS id,
r.NAME
FROM testdb.dbo.people r
JOIN testdb.dbo.relation l
ON l.pid = r.id
AND gender = 'M') AS father
ON l.cid = father.id
Query that prints the names of a child and his parents in individual columns respectively in order of the name of the child.
SELECT c.name as child,
MAX(CASE WHEN p.gender = 'F' THEN p.name END) AS mother,
MAX(CASE WHEN p.gender = 'M' THEN p.name END) AS father
FROM relations r
INNER JOIN public."People" c on c.id = r.cid
INNER JOIN public."People" p on p.id = r.pid
GROUP BY r.cid, c.name ORDER BY c.name;
select b.name as child,c.name as father,d.name as mother from relation a join people b on a.cid=b.id
join people c on a.pid=c.id
join people d on a.pid=d.id where c.gender='m' and d.gender='f'
I have 3 tables
sub
ctn region
1 a
1 a
2 b
3 c
8 n
mta
ctn
1
1
2
3
4
rcr
ctn
1
1
2
3
4
5
I need to find the number of distinct users in every region. In this case the result would be
res
a 1
b 1
c 1
n 1
null 2
if the user isn't in any region then I need to know how many of users like him there are.
What I have so far.
WITH com as(
SELECT DISTINCT ctn
FROM (
SELECT ctn
FROM mta
UNION ALL
SELECT ctn
FROM rcr
) c
)
, distinct_ctn as(
SELECT DISTINCT sub.ctn, com.ctn, sub.region
FROM sub
FULL JOIN com
ON sub.ctn = com.ctn
)
SELECT region, count(*)
FROM distinct_ctn
GROUP BY region;
Have a sub-query where you use UNION to get the distinct cnt values from mta and rcr tables.
RIGHT JOIN table sub with that result, and finally GROUP BY the join result.
select s.region, count(distinct u.ctn)
from sub s
right join (select ctn from mta
union
select ctn from rcr) u
on s.ctn = u.ctn
group by s.region
Suppose i have data like that
ID ParentID Title
1 Null America
2 1 Texas
3 2 Dallas
i want result like that through LINQ/EF or SQL Queries
ID Title
1 America
2 America/Texas
3 America/Texas/Dallas
WITH H AS
(
-- Anchor: the first level of the hierarchy
SELECT id, ParentID, Title, CAST(Title AS NVARCHAR(300)) AS path
FROM TestTABLE
WHERE parentid IS NULL
UNION ALL
-- Recursive: join the original table to the anchor, and combine data from both
SELECT T.id, T.ParentID, T.Title, CAST(H.path + '\' + T.Title AS NVARCHAR(300))
FROM TestTABLE T INNER JOIN H ON T.ParentID = H.id
)
SELECT * FROM H