From SQL to SPL: Total under recursive relationship
A certain database has a ticket table and a work hour table. The ticket table stores the relationship between each ticket and its parent ticket, forming a self-association structure:
ticketid |
parentID |
1 |
6 |
2 |
7 |
3 |
8 |
4 |
9 |
5 |
10 |
6 |
18 |
7 |
19 |
8 |
20 |
9 |
21 |
10 |
22 |
11 |
23 |
12 |
18 |
13 |
19 |
14 |
20 |
15 |
21 |
16 |
22 |
17 |
23 |
18 |
24 |
19 |
25 |
20 |
26 |
21 |
27 |
22 |
28 |
23 |
29 |
24 |
30 |
25 |
30 |
26 |
30 |
27 |
30 |
28 |
30 |
29 |
30 |
30 |
0 |
The work hour table stores multiple working hours corresponding to each ticket:
ticketid |
hours |
0 |
4 |
1 |
2 |
1 |
1 |
2 |
5 |
2 |
1 |
3 |
5 |
3 |
2 |
3 |
2 |
4 |
1 |
4 |
4 |
4 |
1 |
4 |
5 |
5 |
3 |
5 |
2 |
6 |
3 |
6 |
3 |
6 |
2 |
6 |
1 |
6 |
1 |
7 |
1 |
7 |
2 |
7 |
4 |
7 |
2 |
8 |
5 |
8 |
2 |
8 |
4 |
9 |
5 |
9 |
2 |
10 |
5 |
10 |
4 |
10 |
4 |
11 |
1 |
11 |
1 |
12 |
3 |
12 |
2 |
12 |
5 |
13 |
2 |
13 |
2 |
14 |
5 |
14 |
1 |
14 |
2 |
14 |
1 |
15 |
5 |
15 |
5 |
15 |
1 |
15 |
3 |
16 |
2 |
16 |
1 |
16 |
5 |
17 |
4 |
17 |
4 |
18 |
1 |
18 |
5 |
18 |
1 |
19 |
1 |
19 |
1 |
19 |
4 |
19 |
3 |
20 |
2 |
20 |
2 |
20 |
5 |
21 |
3 |
21 |
5 |
22 |
3 |
22 |
4 |
22 |
5 |
23 |
3 |
23 |
2 |
23 |
5 |
23 |
4 |
24 |
4 |
24 |
4 |
24 |
1 |
24 |
4 |
25 |
2 |
25 |
4 |
25 |
3 |
26 |
2 |
26 |
2 |
26 |
4 |
26 |
2 |
26 |
2 |
27 |
2 |
27 |
3 |
28 |
5 |
28 |
1 |
28 |
3 |
28 |
1 |
29 |
1 |
29 |
4 |
30 |
0 |
30 |
0 |
Now we need to calculate the working hours for each ticket and recursively calculate the sum of the working hours for that ticket and all subordinate tickets, which is the total working hours.
MainID |
Direct_hours |
Total_hours |
1 |
3 |
3 |
2 |
6 |
6 |
3 |
9 |
9 |
4 |
11 |
11 |
5 |
5 |
5 |
6 |
10 |
13 |
7 |
9 |
15 |
8 |
11 |
20 |
9 |
7 |
18 |
10 |
13 |
18 |
11 |
2 |
2 |
12 |
10 |
10 |
13 |
4 |
4 |
14 |
9 |
9 |
15 |
14 |
14 |
16 |
8 |
8 |
17 |
8 |
8 |
18 |
7 |
30 |
19 |
9 |
28 |
20 |
9 |
38 |
21 |
8 |
40 |
22 |
12 |
38 |
23 |
14 |
24 |
24 |
13 |
43 |
25 |
9 |
37 |
26 |
12 |
50 |
27 |
5 |
45 |
28 |
10 |
48 |
29 |
5 |
29 |
30 |
0 |
252 |
SQL:
WITH CTE_TREE AS (
SELECT parentid AS parentid, ticketid AS children
FROM tickets t
WHERE parentID <> 0
UNION
SELECT parentid, NULL
FROM tickets
WHERE parentID <> 0
UNION
SELECT ticketid, NULL
FROM tickets
)
, CTE_TRAVERSE AS (
SELECT parentid AS mainId, children AS nextParent
FROM CTE_TREE
UNION ALL
SELECT t.mainId, tree.children
FROM CTE_TREE tree
INNER JOIN CTE_TRAVERSE t
ON t.nextParent = tree.parentid
WHERE tree.children <> ''
)
SELECT t.MainID
, SUM(CASE WHEN t.nextparent IS NULL THEN h.Hours END) AS Direct_hours
, SUM(h.Hours) AS Total_hours
FROM CTE_TRAVERSE t
INNER JOIN Hours h
ON h.ticketid = t.nextparent
OR (h.ticketid = t.mainID AND t.nextparent IS NULL)
GROUP BY t.mainId
SQL requires multiple subqueries to implement self-association and recursive relationships, and the code is complex and difficult to understand. SPL directly provides reference functions to establish self-associations and recursive functions to take all subordinate nodes:
https://try.esproc.com/splx?2SJ
A |
|
1 |
$select t.ticketid ticketid,t.parentID parentID,h.hours hours from tickets.txt t left join (select ticketid,sum(hours) hours from hours.txt group by ticketid) h on t.ticketid=h.ticketid |
2 |
>A1.switch(parentID,A1:ticketid) |
3 |
=A1.new(ticketid:MainID,hours:Direct_hours,hours+A1.nodes(parentID,~).sum(hours):Total_hours) |
A1: Load data and calculate the direct working hours for each ticket based on the ticket table.
A2: Set the parent ticket field of each record to point to the parent ticket record and establish a self-association relationship. The switch function can modify field values to records.
A3: Create a new two dimensional table, where the total working hours of the current ticket are equal to the direct working hours of the current ticket plus the sum of the working hours of all its subordinate sub tickets. The function nodes can recursively calculate all the subordinate records of a certain record.
Question source:https://stackoverflow.com/questions/78089375/how-to-add-total-hours-for-a-ticket-including-all-child-tickets
SPL Official Website 👉 https://www.esproc.com
SPL Feedback and Help 👉 https://www.reddit.com/r/esProcSPL
SPL Learning Material 👉 https://c.esproc.com
SPL Source Code and Package 👉 https://github.com/SPLWare/esProc
Discord 👉 https://discord.gg/2bkGwqTj
Youtube 👉 https://www.youtube.com/@esProc_SPL