Clarity

 View Only

 Risks aggregated in Hierarchy

Jump to  Best Answer
Lara García Farace's profile image
Lara García Farace posted Jul 14, 2026 03:40 AM

Hi Clarity Community!

I'm trying to get an aggregated view of our risks and issues and I believe the best way to do this would be in hierarchies (if anyone has other suggestions, I'm open to hearing them). I would like for it to be in a hierarchical view, where I can see all of the Clients (top investment level) with open R&I at any level, and expand to see what child investments have R&I.

In order to do this, since we have many investments without R&I, I've created 2 aggregated attribute on the Investment object that counts the amount if R&I (one for each). 

However, I would like for this amount to roll-up based on the parent investment. 

For example:

  • Investment A = 2 risks
  • Investment B (parent to investment A) = 3 risks
  • Investment B's total risk count should be 5. (I don't mind if this is on a separate attribute.)

The problem I'm experiencing is that I can't find a way to create that roll-up.

  1. The aggregate attribute only counts the R&I for that specific investment. It doesn't take into account the child investments.
  2. I've tried creating a process, but:
    1. If I select the Investment as an object, I can't add risks
    2. If I select risks as the object, I can't tie it to parent investments

Has anyone come accross a similar use case? How was it solved?

Thanks in advance!

Ming Cheung's profile image
Broadcom Employee Ming Cheung  Best Answer

There is a way you can do the roll up using our OOTB hierarchies.  The challenge is Aggregated Calculated Attributes are not available in Hierarchies but calculated attributes are.

Here's what I did:

  1. Create the Aggregated Calculated Attribute on the Investment Object (I usually count the unique identifier).  This will give you the count of risks on your investment.
  2. Create a second, calculated attribute, using the attribute created in Step 1 and multiply it by 1 (or add 0, if you like).  This will return the count of risks again, but this time as a simple calculated attribute.
  3. Create an API IDs for both attributes
  4. Go to a Hierarchy --> Investments Module.  Select the View Options and click Manage Metrics.  The new metric created is based on the previously created Calculated Risk Count (the Aggregated Version does not appear in the list) with the scope "Self and Children"
  5. Below is the result: Risk Count 2 is the Calculated attribute (where Risk Count was the Aggregated Calculated) and Risk Count 3 is the Hierarchical Metric created in Step 4.

This was done in Release 16.4.2 which also supports scheduling of hierarchy investments based on the Parent attribute.

Suman Pramanik's profile image
Broadcom Employee Suman Pramanik
Hi,
this is a common challenge once you have several levels of investment hierarchy.
 
You're right that this can't be solved with a standard aggregated attribute or a Process. Both of those only look at direct relationships, and an investment hierarchy can be many levels deep, so neither one will walk up automatically and sum totals for you.
 
The good news is Clarity already tracks the full expanded hierarchy for you, so you don't need to build recursive logic yourself. Behind the scenes, when you set up parent/child relationships between investments (Program → Project, or a general Investment Hierarchy), Clarity stores the direct relationships in one table, but also maintains a second table that expands this out to every descendant at  every level — not just immediate children. That second table is what makes this solvable with a single query instead of a recursive one.
 
How I'd approach it:
 
1. Calculate the true roll-up with one query. Using that expanded hierarchy table, you can get, for any investment, the total Risk/Issue count across all of its descendants — no matter how many levels down — in a single join/group-by. No recursion required.
 
2. Decide where that number needs to live:
   - If you want it stored as a real attribute on the Investment (so it's usable in other views, filters, or NSQL portlets), run this as a scheduled job (via a GEL script) that recalculates the totals and writes them into your existing custom rollup attributes on whatever cadence makes sense for you (hourly/nightly).
   - If it's only needed for this one hierarchical dashboard, you can skip storing it altogether and have your report/portlet query the hierarchy table directly at render time. That's less to maintain and it's always current.
 
3. For the hierarchical view itself (Client → child investments, expandable), that same expanded hierarchy table includes a "level" indicator for each descendant, which is exactly what you'd use to drive indentation/grouping in a report or portlet for the drill-down experience you're describing.

Clarity stores investment hierarchy relationships (Program→Project, or general Investment Hierarchy) in `INV_HIERARCHIES`, but that table only holds direct parent/child pairs, one level at a time. Clarity also maintains an expanded version of that table, `RPT_INV_HIERARCHY`, which includes every descendant at every level, not just immediate children — with a `THE_LEVEL` column telling you how many levels down each row is. It's kept in sync automatically as you maintain your hierarchy, so you can query it directly without rebuilding anything yourself.

Key columns on RPT_INV_HIERARCHY:
- PARENT_ID — the ancestor investment
- CHILD_ID — a descendant investment (direct or indirect)
- THE_LEVEL — how many levels down the child is from the parent
- SEQUENCE_STR — for ordering within the hierarchy display
 
Example query — total risk count per investment, rolled up across all descendants:
 
SELECT h.parent_id AS investment_id,
       COUNT(r.id)  AS total_risk_count
FROM   rpt_inv_hierarchy h
JOIN   rim_risks_and_issues r
       ON r.pk_id = h.child_id
      AND r.type_code = 'RISK'
WHERE  h.parent_id = :investment_id
GROUP  BY h.parent_id;

 This only counts descendants — if you also want the investment's own direct risks included in its total, add a `UNION ALL` against `rim_risks_and_issues` filtered directly on the investment itself (`r.pk_id = :investment_id AND r.type_code = 'RISK'`)

Lara García Farace's profile image
Lara García Farace

Hi Suman, 

Thanks for your answer!

I'm interested in using this as a real attribute so I'm going to move forward with the scheduled job option. 

To make sure I understand, I need to:

  1. Create a query that will calculate the roll-up value for investments. I've tried the query you posted but I've gotten an error due to the structure for a Niku query.
  2. Once I create the query, I'll create the job that updates the attribute. How do I reference the query here?

Thank you!

Suman Pramanik's profile image
Broadcom Employee Suman Pramanik
Hi Lara

Since you are going with the scheduled job option using a GEL script, you actually don't need to create a Niku Query (NSQL) in the Clarity UI. NSQL is primarily used for Portlets and Lookups.
 
For a GEL script, you will embed the standard SQL directly within the script using the <sql:query> tag. The script will execute the query to calculate the totals, and then update the custom attribute on the parent investments.

Here is a high-level overview of how the GEL script would be structured:

  • Connect to the Database: Use <gel:setDataSource dbId="Niku"/> to connect to the Clarity database.
  • Execute the Query: Use <sql:query> to run the standard SQL and store the results in a variable.
  • Loop and Update: Iterate through the results and update the investment records. The safest and most supported way to update investment attributes in a GEL script is by constructing a XOG (XML Open Gateway) payload and executing it, rather than doing direct SQL updates.

Here is a simplified example of what the GEL script might look like:

<gel:script xmlns:core="jelly:core"
            xmlns:gel="jelly:com.niku.union.gel.GELTagLibrary"
            xmlns:sql="jelly:sql"
            xmlns:xog="http://www.niku.com/xog">

    <!-- 1. Connect to the Clarity database -->
    <gel:setDataSource dbId="Niku" />

    <!-- 2. Execute the standard SQL query -->
    <sql:query var="riskCounts">
        SELECT h.parent_id AS investment_id,
               inv.code AS investment_code,
               COUNT(r.id) AS total_risk_count
        FROM rpt_inv_hierarchy h
        JOIN rim_risks_and_issues r ON r.pk_id = h.child_id AND r.type_code = 'RISK'
        JOIN inv_investments inv ON inv.id = h.parent_id
        GROUP BY h.parent_id, inv.code
    </sql:query>

    <!-- 3. Loop through the results and build a XOG payload to update the custom attribute -->
    <core:forEach items="${riskCounts.rows}" var="row">
        <gel:log>Investment: ${row.investment_code} has ${row.total_risk_count} total risks.</gel:log>
        
        <!-- 
          Construct XOG XML for the Project/Investment object here 
          and use <soap:invoke> or <xog:invoke> to update your custom attribute (e.g., c_total_risks)
        -->
    </core:forEach>

</gel:script>
If you still want to use NSQL for a Portlet later: The error you received when trying to create a Niku query is because NSQL requires specific @SELECT...@ and @FROM...@ constructs. The NSQL version of the query would look something like this: 
SELECT @SELECT:DIM:USER_DEF:IMPLIED:INVESTMENT:h.parent_id:investment_id@,
       @SELECT:METRIC:USER_DEF:IMPLIED:COUNT(r.id):total_risk_count@
FROM rpt_inv_hierarchy h
JOIN rim_risks_and_issues r ON r.pk_id = h.child_id AND r.type_code = 'RISK'
WHERE @FILTER@
GROUP BY h.parent_id
HAVING @HAVING@