I am trying to calculate totals for each node of a tree structure, Calculating the total depends on roll up type
I have Structure like below
if node type is current list = Look to current node, no need I go down in the tree
if node type is child = ignore the current node and go down
if node type is current and child = I include the current node
and go down
Assume my Starting Point will be B1 : so the total score will be = (20 +40 +110 +60 +90)
Assume my Starting Point C2 : Score is 110
I managed to get all children but when it comes to the rollup I get stuck please help
Sample Data Script
+--------+----------+------+------------+-------------------+------------------+
| Teamid | ParentId | Name | ParentName | Type | Key Result Value |
+--------+----------+------+------------+-------------------+------------------+
| 1 | null | A1 | Null | Current and Child | 10 |
| 2 | 1 | B1 | A1 | Current and Child | 20 |
| 3 | 1 | B2 | A1 | Current and Child | 30 |
| 4 | 2 | C1 | B1 | Current List | 40 |
| 5 | 2 | C2 | B1 | Child List | 50 |
| 6 | 2 | C3 | B1 | Current and Child | 60 |
| 7 | 4 | D1 | C1 | Current and Child | 70 |
| 8 | 5 | D2 | C2 | Child List | 80 |
| 9 | 6 | D3 | C3 | Current and Child | 90 |
| 10 | 7 | E1 | D1 | Current List | 100 |
| 11 | 8 | E2 | D2 | Current and Child | 110 |
+--------+----------+------+------------+-------------------+------------------+
TreeTable Script:
CREATE TABLE TreeTable(
Teamid INTEGER NOT NULL PRIMARY KEY
,ParentId INTEGER
,Name VARCHAR(2) NOT NULL
,ParentName VARCHAR(4)
,Type VARCHAR(17) NOT NULL
,Key_Result_Value INTEGER NOT NULL
);
INSERT INTO TreeTable(Teamid,ParentId,Name,ParentName,Type,Key_Result_Value) VALUES (1,NULL,'A1',NULL,'Current and Child',10);
INSERT INTO TreeTable(Teamid,ParentId,Name,ParentName,Type,Key_Result_Value) VALUES (2,1,'B1','A1','Current and Child',20);
INSERT INTO TreeTable(Teamid,ParentId,Name,ParentName,Type,Key_Result_Value) VALUES (3,1,'B2','A1','Current and Child',30);
INSERT INTO TreeTable(Teamid,ParentId,Name,ParentName,Type,Key_Result_Value) VALUES (4,2,'C1','B1','Current List',40);
INSERT INTO TreeTable(Teamid,ParentId,Name,ParentName,Type,Key_Result_Value) VALUES (5,2,'C2','B1','Child List',50);
INSERT INTO TreeTable(Teamid,ParentId,Name,ParentName,Type,Key_Result_Value) VALUES (6,2,'C3','B1','Current and Child',60);
INSERT INTO TreeTable(Teamid,ParentId,Name,ParentName,Type,Key_Result_Value) VALUES (7,4,'D1','C1','Current and Child',70);
INSERT INTO TreeTable(Teamid,ParentId,Name,ParentName,Type,Key_Result_Value) VALUES (8,5,'D2','C2','Child List',80);
INSERT INTO TreeTable(Teamid,ParentId,Name,ParentName,Type,Key_Result_Value) VALUES (9,6,'D3','C2','Current and Child',90);
INSERT INTO TreeTable(Teamid,ParentId,Name,ParentName,Type,Key_Result_Value) VALUES (10,7,'E1','D1','Current List',100);
INSERT INTO TreeTable(Teamid,ParentId,Name,ParentName,Type,Key_Result_Value) VALUES (11,8,'E2','E2','Current and Child',110);
My Attempt:
WITH
CTE_Groups
AS
(
SELECT
TreeTable.teamid AS StartID
,TreeTable.Name AS StartName
,TreeTable.teamid
,TreeTable.ParentID
,TreeTable.Name
,1 AS Lvl
,TreeTable.Type
,TreeTable.Key_Result_Value
FROM TreeTable
UNION ALL
SELECT
CTE_Groups.StartID
,CTE_Groups.StartName
,TreeTable.teamid
,TreeTable.ParentID
,TreeTable.Name
,CTE_Groups.Lvl + 1 AS Lvl
,TreeTable.Type
,TreeTable.Key_Result_Value
FROM
TreeTable
INNER JOIN CTE_Groups ON CTE_Groups.teamid = TreeTable.ParentID
)
select * from CTE_Groups
order by startid,lvl
ScreenShot of my Attempt to get all children of the node, but then I got stuck on how to exclude the nodes based on type, because I need to have a vision of the complete path:
Please Help
Expected Result:
+--------+-----------------------+
| TeamID | Score |
+--------+-----------------------+
| E1 | 100 |
| D1 | 70 + 100 |
| C1 | 40 |
| E2 | 110 |
| D2 | 110 |
| C2 | 110 |
| D3 | 90 |
| C3 | 60+90 |
| B1 | 20+40+110+60+90 |
| B2 | 30 |
| A1 | 10+30+20+40+110+60+90 |
+--------+-----------------------+
Using recursion to list the node children is a good start. Using case expressions you can also keep track of the group type and when to add or ignore values (ignoring = using 0 instead of the real node value).
Solution
with rcte as
(
select t.Name as GroupName,
t.Type as GroupType,
t.Name,
t.Type,
case t.Type
when 'Child list' then 0 -- if the current node must be ignored, then the current value changes to 0
else t.Key_Result_Value
end as Value
from TreeTable t
union all
select r.GroupName,
r.GroupType,
t.Name,
case r.Type
when 'Current list' then 'Current list' -- if the parent was the end of the sum, then it stays the end of the sum
else t.Type
end,
case
when r.Type = 'Current list' then 0 -- if the parent was the end of the sum, then the current value changes to 0
when t.Type = 'Child list' then 0 -- if the current node must be ignored, then the current value changes to 0
else t.Key_Result_Value
end
from rcte r
join TreeTable t
on t.ParentName = r.Name
)
select r.GroupName,
sum(r.Value) as GroupSum,
string_agg(case when r.Value <> 0 then convert(nvarchar(3), r.Value) end, '+') as GroupSumFormula
from rcte r
group by r.GroupName
order by r.GroupName;
Result
GroupName GroupSum GroupSumFormula
--------- -------- ---------------------
A1 360 10+20+30+40+60+90+110
B1 320 20+40+60+90+110
B2 30 30
C1 40 40
C2 110 110
C3 150 60+90
D1 170 100+70
D2 110 110
D3 90 90
E1 100 100
E2 110 110
Fiddle to see things in action.
I am working on a Store Procedure where I need to update records from from table 1 into table 2.
Table1: contains the following 4 columns
----------------------------------------------
| ID | TableName | ColumnName | Value |
----------------------------------------------
| 1 | [UserDetails] | [FinalScore] | 92 |
| 2 | [UserDetails] | [FinalScore] | 89 |
| 3 | [UserDetails] | [FinalScore] | 65 |
| 4 | [UserDetails] | [FinalScore] | 91 |
| 5 | [UserDetails] | [FinalScore] | 76 |
| 1 |[EmployeeDetail]| [ScoreData] | 0.91 |
----------------------------------------------
UserDetails table
-----------------------------------------------------------
| UserID | UserName | ContactNo | FinalScore |
-----------------------------------------------------------
| 1 | John G | +13288992342 | 0 |
| 2 | Leonard J | +14581232342 | 0 |
| 3 | Max R | +17123992342 | 0 |
| 4 | Robert H | +15688992122 | 0 |
| 5 | Jimmy L | +1328996782 | 0 |
-----------------------------------------------------------
Need to load all the data from table1 into the corresponding destination table for large amount of data (30,000 to 60,000) records.
Table1 contains the ID (from ID Column in table1) and FinalScore (from ColumnName Column in table1) in the destination table (from TableName Column in table1) where the value (from Value Column in table1) needs to be loaded.
End Result of UserDetails table after SP execution :
-----------------------------------------------------------
| UserID | UserName | ContactNo | FinalScore |
-----------------------------------------------------------
| 1 | John G | +13288992342 | 92 |
| 2 | Leonard J | +14581232342 | 89 |
| 3 | Max R | +17123992342 | 65 |
| 4 | Robert H | +15688992122 | 91 |
| 5 | Jimmy L | +1328996782 | 76 |
-----------------------------------------------------------
I am not sure how to load the data from "table1" into destination table (userdetails table) for bulk data as update query in a loop is taking very long time to complete.
It's not pivot what you're after but a simple join:
select
a.userid, a.contactno, b.finalscore
from UserDetails a
join table1 b on a.id = b.id
alternatively, if you want to update the old table without creating a new one, you can update join
SQL update query using joins
I have two tables:
ProjectProduct (two IDs for project and product) and
ProductStatus (which contains quality ratings for products).
Table: ProjectProduct
| productID | projectID |
| --------- | --------- |
| 39 | 26 |
| 40 | 26 |
| 41 | 26 |
| 42 | 26 |
Table: ProductStatus
| id | projectID | productID | typeID | Status | Comment | RatedBy |
| --- | --------- | --------- | ------ | ------ | ------------ | ------- |
| 1 | 26 | 39 | 2 | 30 | comm1 | 0 |
| 2 | 26 | 39 | 2 | 70 | comm2 | 0 |
| 22 | 26 | 39 | 1 | 70 | diff type | 0 |
| 3 | 26 | 39 | 2 | 100 | comm3 | 0 |
| 4 | 26 | 39 | 2 | 70 | diff ratedBy | 1 |
| 5 | 26 | 39 | 2 | 100 | comm5 | 0 |
| 6 | 26 | 39 | 2 | 30 | comm6 | 0 |
I need to join those two tables so that every product in the ProjectProduct table will display a Status value even if there is no corosponding entry in the ProductStatus table.
In above example only productID 39 exists in both tables. To show all productIDs the output should contain a zero value in the Status column for productIDs 40 to 42.
This is the part that I cannot figure out. For example the ProductStatus TypeID can contain 1 or 2. TypeID 2 has to be distinguished between RatedBy which can contain 0 or 1. Do I need the table or select statement to reflect all possible permutations?
Also only the row with the highest ID grouped by projectID, productID, typeID, RatedBy should be picked where there is an existing rating.
Desired output:
I also created a SQL Fiddle
I hope you can guide me in the right direction.
Thank you.
Query
SELECT ProjectProduct.projectID, ProjectProduct.productID, ProductStatus.typeid,ProductStatus.status,ProductStatus.Comment,ProductStatus.ratedBY
FROM ProjectProduct
left join
(
SELECT max(ID) id, productID,projectID
FROM ProductStatus
where typeID = 2
and ratedBY = 0
group BY productID,projectID ) maxproduct on ProjectProduct.productID = maxproduct.productID and ProjectProduct.projectID = maxproduct.projectID
left join ProductStatus on ProductStatus.id = maxproduct.ID
Output
you can use temp table like that:
select Max(Id) maxID ,ProductId,ProjectId into #Temp1 from ProductStatus
where typeID=2 and RatedBy=0
group by ProductId,ProjectId
select * into #Temp2 from ProductStatus where Id In (select MaxId from #Temp1)
select p.ProjectId,p.ProductId, 2 as typeID,isnull(t.status,0) as Status,t.Comment,0 as RatedBy
from ProjectProduct p left join #Temp2 t on p.ProductId=t.ProductId and p.ProjectId=t.ProjectId
I have two tables as follows:
Table1:
ID | FName | LName
1 | A1 | A2
2 | B1 | B2
3 | C1 | C2
Table2:
ID | Price | Month | T1ID
1 | 5 | 1 | 1
2 | 5 | 1 | 2
3 | 5 | 2 | 3
Result:
Where Month = '1'
ID | FName | LName | Price | Month | T1ID
1 | A1 | A2 | 5 | 1 | 1
2 | B1 | B2 | 5 | 1 | 2
NULL| C1 | C2 | NULL | NULL | 3
Where Month = '2'
ID | FName | LName | Price | Month | T1ID
NULL| A1 | A2 | NULL | NULL | 1
NULL| B1 | B2 | NULL | NULL | 2
3 | C1 | C2 | 5 | 2 | 3
Looks like a left join with multiple join conditions:
SELECT t2.ID, t1.FName, t1.LName, t2.Price, t2.Month, t1.ID
FROM Table1 t1
LEFT JOIN Table2 t2 ON t1.ID = t2.T1ID AND t2.Month = '1' -- or '2'
The trick is to do filtering by adding additional condition to ON clause, which helps to filter records during the join. If you used the condition in WHERE clause, some records would be filtered out from the results, which is not what you expect.
I have the next table, is called: mytable:
---------------------------------
|id | date | name|actionCount |
---------------------------------
|a1 |03.03.12| ba | 12 |
|a3 |06.02.13| ba | 7 |
|a1 |06.02.13| ca | 2 |
|a3 |06.02.13| ba | 9 |
|a1 |06.06.13| ba | 2 |
|--------------------------------
I want to get the distinct id and name, and sum them count.
so I have to get:
------------------------
|id | name|actionCount |
------------------------
|a1 | ba | 14 |
|a3 | ba | 16 |
|a1 | ca | 2 |
------------------------
I tried:
SELECT DISTINCT id,name,SUM(actionCount) FROM mytable GROUP BY actionCount
but I got:
Column 'mytable.id' is invalid in the select list because it is not contained in either
an aggregate function or the GROUP BY clause.
Any help appreciated!
You can try like this...
SELECT id,name,SUM(actionCount) FROM mytable GROUP BY id,name