Implement complex data analysis by using the do-while node
A do-while node in DataWorks works like a do-while loop in programming: it runs a set of inner nodes repeatedly until a condition you define evaluates to false. Use it to process the same data or task multiple times without duplicating your workflow. This topic walks through a complete example—collecting monthly order statistics for an e-commerce dataset—to show how to set up, configure, and test a do-while node.
Background
DataWorks do-while nodes let you define a looping workflow and control when to exit. You can use a do-while node alone, or pair it with an assignment node to loop through a result set.
Scenario
Consider an e-commerce order table partitioned by day, where the partition key ds is formatted as YYYYMMDD. For example, all orders placed on September 1, 2022 are stored in partition 20220901.
| id | user_id | order_amount | ds |
|----|---------|--------------|----------|
| 1 | 1001 | 500 | 20220901 |
| 2 | 1002 | 1500 | 20220901 |
| 7 | 1003 | 890 | 20221021 |
| 8 | 1004 | 240 | 20221021 |Goal: For each of the 12 months in 2022, calculate the total order count and amount for the last 30 days, last 60 days, and last 90 days from the first of that month.
| stat_day | stat_type | order_total | order_amount_total |
|----------|-----------|-------------|--------------------|
| 20220901 | 30d | 10 | 0 |
| 20220901 | 60d | 20 | 0 |
| 20220901 | 90d | 30 | 0 |Solution: Run 12 loops—one per month—using a do-while node. Inside each loop, three ODPS SQL nodes calculate the 30-day, 60-day, and 90-day statistics. The built-in variable ${dag.loopTimes} tracks the current loop count (1 for January, 2 for February, and so on through 12 for December), so you can dynamically compute the correct partitions in each SQL query.
do-while node constraints
| Constraint | Detail |
|---|---|
| Maximum loops | 128. If you need more iterations, split the task across multiple do-while nodes. |
| Concurrent execution | Not supported. Each loop must complete before the next one starts. |
${dag.loopTimes} | Built-in variable. Starts at 1 and increments by 1 each loop. All inner nodes can reference it. |
| Testing in DataStudio | Not supported in standard mode workspaces. Commit and deploy to Operation Center first, then run from there. |
Prerequisites
Before you begin, make sure that you have:
An activated MaxCompute service and a MaxCompute project. For more information, see Activate MaxCompute and Create a MaxCompute project.
DataWorks Standard Edition or a higher edition. For more information, see Purchase guide and Differences among DataWorks editions.
A DataWorks workspace in standard mode. For more information, see Upgrade a workspace from basic mode to standard mode.
A MaxCompute compute engine associated with your workspace. For more information, see Associate a MaxCompute compute engine with a workspace.
Prepare data
Log on to the MaxCompute console. In the left-side navigation pane, choose DataWorks > Data Development to go to the DataStudio page.
In the left-side navigation pane, click Scheduled Workflow.
Click the desired workflow and choose MaxCompute > Data Analytics. Right-click Data Analytics and choose Create Node > ODPS SQL to create an ODPS SQL node named
init_test_data.
In the code editor for the
init_test_datanode, enter the following SQL:-- Create an order table. CREATE TABLE orders ( id BIGINT ,user_id BIGINT -- The user ID. ,order_amount BIGINT -- The order amount. ) PARTITIONED BY ( ds STRING -- The order date. ) ; -- Insert order data. INSERT INTO orders PARTITION (ds = '20220901') VALUES (1,1001,500) ,(2,1002,1500); INSERT INTO orders PARTITION (ds = '20220905') VALUES (3,1005,260) ,(4,1002,780); INSERT INTO orders PARTITION (ds = '20221010') VALUES (5,1003,890) ,(6,1004,240); INSERT INTO orders PARTITION (ds = '20221021') VALUES (7,1003,890) ,(8,1004,240); INSERT INTO orders PARTITION (ds = '20221025') VALUES (9,1002,260) ,(10,1007,780); -- Create an order statistics table. CREATE TABLE orders_stat ( stat_day STRING -- The statistical date (first day of each month). ,stat_type STRING -- The statistical type. ,order_total BIGINT -- The total number of orders. ,order_amount_total BIGINT -- The order amount. ) ;Commit the
init_test_datanode to the production environment and backfill data.On the toolbar, click the
icon and then the
icon to save and commit the node. When prompted, enter a change description and choose whether to run code review and smoke testing. > Note: Configure the Rerun and Parent Nodes parameters on the Properties tab before committing. If code review is enabled, the node can only be deployed after a reviewer approves it. For more information, see Code review. To validate your code before deployment, see Perform smoke testing.If your workspace is in standard mode, click Deploy in the upper-right corner after committing. For more information, see Workspace in standard mode and Deploy nodes.
In the upper-right corner, click Operation Center. Choose Cycle Task Maintenance > Cycle Task. In the cycle task list, click
init_test_data. In the directed acyclic graph (DAG) on the right, right-click the node and select Test to initialize data.
Freeze the
init_test_datanode. This node is for one-time initialization. After it runs successfully, freeze it to prevent repeated execution. In the cycle task list, right-click the node and select Freeze.
Create a do-while node and configure inner nodes
Make sure your workspace is associated with a MaxCompute compute engine before proceeding. For more information, see Associate a MaxCompute compute engine with a workspace.
Create the do-while node
Log on to the DataWorks console. In the top navigation bar, select a region. In the left-side navigation pane, choose Data Development and O&M > Data Development. Select your workspace and click Go to Data Development.
On the DataStudio page, move the pointer over the
icon and choose Create Node > General > do-while. Alternatively, find the target workflow, click the workflow name, right-click General, and choose Create Node > do-while.In the Create Node dialog box, configure the Name and Path parameters, then click Confirm.
Add inner nodes
Double-click the do-while node name to open its configuration tab.
Delete the default sql node: right-click it and choose Delete Node, then click OK.
Create the following nodes inside the do-while node:
Three ODPS SQL nodes (choose MaxCompute > ODPS SQL): name them
30_day,60_day, and90_day.One Shell node (choose General > Shell): name it
echo.
On the canvas, drag connections to configure the following dependency order:
start→echo→30_day,60_day,90_day→endTheechonode runs first, followed by the three SQL nodes in parallel, and theendnode runs last.
Write the node code
After editing a Shell node, save it immediately. Shell node changes are not tracked by commit, so unsaved edits may not take effect.
`echo` node — logs the current loop count:
#!/bin/bash
echo "loop times: ${dag.loopTimes}"`30_day` node — inserts 30-day order statistics for the first day of each month. The ${dag.loopTimes} variable is padded to two digits and used to build the partition boundary:
INSERT INTO orders_stat
SELECT CONCAT('2022',LPAD(${dag.loopTimes},2,'0'),'01') AS stat_day
,'30d' AS stat_type
,COUNT(id) AS order_total
,nvl(SUM(order_amount),0) AS order_amount_total
FROM orders
WHERE
-- The first day of the prior month.
ds >= REPLACE(ADD_MONTHS(TO_DATE(CONCAT('2022',LPAD(${dag.loopTimes},2,'0'),'01'),'yyyyMMdd'),-1),'-','')
-- The first day of the current month.
AND ds < CONCAT('2022',LPAD(${dag.loopTimes},2,'0'),'01')
;The SQL uses these built-in MaxCompute functions:
String and date functions: CONCAT, LPAD, REPLACE, TO_DATE, ADD_MONTHS
`60_day` node — same structure as 30_day, with the ADD_MONTHS offset changed to -2:
INSERT INTO orders_stat
SELECT CONCAT('2022',LPAD(${dag.loopTimes},2,'0'),'01') AS stat_day
,'60d' AS stat_type
,COUNT(id) AS order_total
,nvl(SUM(order_amount),0) AS order_amount_total
FROM orders
WHERE
-- The first day of two months ago.
ds >= REPLACE(ADD_MONTHS(TO_DATE(CONCAT('2022',LPAD(${dag.loopTimes},2,'0'),'01'),'yyyyMMdd'),-2),'-','')
-- The first day of the current month.
AND ds < CONCAT('2022',LPAD(${dag.loopTimes},2,'0'),'01')
;`90_day` node — same structure, with the ADD_MONTHS offset changed to -3:
INSERT INTO orders_stat
SELECT CONCAT('2022',LPAD(${dag.loopTimes},2,'0'),'01') AS stat_day
,'90d' AS stat_type
,COUNT(id) AS order_total
,nvl(SUM(order_amount),0) AS order_amount_total
FROM orders
WHERE
-- The first day of three months ago.
ds >= REPLACE(ADD_MONTHS(TO_DATE(CONCAT('2022',LPAD(${dag.loopTimes},2,'0'),'01'),'yyyyMMdd'),-3),'-','')
-- The first day of the current month.
AND ds < CONCAT('2022',LPAD(${dag.loopTimes},2,'0'),'01')
;`end` node — controls when the loop exits. Double-click the end node, select Python from the Language drop-down list, and enter:
if ${dag.loopTimes} < 12:
print True
else:
print FalseWhen ${dag.loopTimes} is less than 12, the loop continues. When it reaches 12 (December), the loop ends—giving you one iteration per month across all 12 months of 2022.
Commit and deploy
On the do-while node configuration tab, click the
icon to save.Click the
icon to commit. In the Submit dialog box, enter a Change description and choose whether to enable code review.ImportantConfigure the Rerun and Parent Nodes parameters on the Properties tab before committing. If code review is enabled, the node is deployed only after the code passes review. For more information, see Code review.
If your workspace is in standard mode, click Deploy in the upper-right corner to push the node to the production environment.
Test and verify results
Do-while nodes cannot be tested directly in DataStudio. To run and verify the node, use Operation Center.
If you use the value passed by an assignment node in the do-while node, run both the assignment node and the do-while node during the test in Operation Center.
Run the do-while node
In the upper-right corner of the DataStudio page, click Operation Center.
In the left-side navigation pane, choose Cycle Task Maintenance > Cycle Task.
In the task list, right-click the
do_while_testnode and choose Run > Backfill Data for Current Node.The SQL in this example does not depend on the Data Timestamp parameter, so the default value works fine.
To monitor progress, right-click
do_while_testin the DAG and select View Runtime Log.
View loop-level logs
In the task DAG, right-click the node and select View Internal Nodes to open the do-while node's inner view. The inner view has three panes:
Left: rerun history, with one record per run instance.
Middle: loop record list showing all loops and their status.
Right: details for the selected loop, including each inner node's status.
In the middle pane, click a completed loop. In the right pane, right-click a node and select View Runtime Log to read its output.
To check the
echonode's output for loop 3, click Loop 3 in the middle pane, then view the log for theechonode. The expected output is:loop times: 3
How the loop works:
Execution starts at the
startnode.Inner nodes run in the order defined by their dependencies.
The
endnode evaluates the exit condition.If the condition returns
True, the next loop starts. If it returnsFalse, the do-while node ends.
Verify the output data
Create an ODPS SQL node and run:
SELECT * FROM orders_stat;Expected result (36 rows, three stat types for each of the 12 months):
| stat_day | stat_type | order_total | order_amount_total |
|----------|-----------|-------------|--------------------|
| 20220101 | 60d | 0 | 0 |
| 20220101 | 30d | 0 | 0 |
| 20220101 | 90d | 0 | 0 |
| 20220201 | 60d | 0 | 0 |
| 20220201 | 30d | 0 | 0 |
| 20220201 | 90d | 0 | 0 |
| 20220301 | 30d | 0 | 0 |
| 20220301 | 60d | 0 | 0 |
| 20220301 | 90d | 0 | 0 |
| 20220401 | 30d | 0 | 0 |
| 20220401 | 90d | 0 | 0 |
| 20220401 | 60d | 0 | 0 |
| 20220501 | 30d | 0 | 0 |
| 20220501 | 90d | 0 | 0 |
| 20220501 | 60d | 0 | 0 |
| 20220601 | 60d | 0 | 0 |
| 20220601 | 30d | 0 | 0 |
| 20220601 | 90d | 0 | 0 |
| 20220701 | 90d | 0 | 0 |
| 20220701 | 30d | 0 | 0 |
| 20220701 | 60d | 0 | 0 |
| 20220801 | 60d | 0 | 0 |
| 20220801 | 90d | 0 | 0 |
| 20220801 | 30d | 0 | 0 |
| 20220901 | 90d | 0 | 0 |
| 20220901 | 60d | 0 | 0 |
| 20220901 | 30d | 0 | 0 |
| 20221001 | 90d | 4 | 3040 |
| 20221001 | 60d | 4 | 3040 |
| 20221001 | 30d | 4 | 3040 |
| 20221101 | 30d | 16 | 8860 |
| 20221101 | 90d | 20 | 11900 |
| 20221101 | 60d | 20 | 11900 |
| 20221201 | 90d | 20 | 11900 |
| 20221201 | 60d | 16 | 8860 |
| 20221201 | 30d | 0 | 0 |The output reflects the sample data inserted in the preparation step: orders are concentrated in September and October 2022, so statistics for earlier months are 0.