How to merge lines and calculate average data on a CDT

Certified Senior Developer

Hi,

I have a CDT that contains many lines. How would you construct a new CDT (new local variable) with merged lines (with average calculations) depending of a field values ? (like the picture below) 

Naively, I would use a foreach and create some lists, but I'm sure Appian provides some great functions to make this stuff easier :-)

(the question is not SQL-query oriented, I'm looking the best way to do it with SAIL from an existing cdt)

Regards

  Discussion posts and replies are publicly visible

  • a!localVariables(
      local!myData: {
        a!map(
          id: 1,
          typeId: 1,
          value: 10
        ),
        a!map(
          id: 2,
          typeId: 1,
          value: 15
        ),
        a!map(
          id: 3,
          typeId: 2,
          value: 5
        ),
        a!map(
          id: 4,
          typeId: 2,
          value: 22
        )
      },
      local!uniqueTypes: union(local!myData.typeId,local!myData.typeId),
      local!aggregateValues: a!forEach(
        local!uniqueTypes,
        a!map(
          id: fv!index,
          typeId: fv!item,
          value: sum(index(
            local!myData.value,
            wherecontains(tointeger(fv!item),tointeger(local!myData.typeId)),
            {}
          ))
        )
      ),
      local!aggregateValues
    )

    The above code should work

  • 0
    Certified Senior Developer
    in reply to Danny Verb

    Thanks a lot Danny. I would probably have coded almost the same thing in 3 times more times... ;-)

    but is there no other way to do it without a foreach ? with a native Appian function for example...

  • 0
    Appian Employee
    in reply to cedric01

    If your data is already in SAIL, then no there's no way to group and aggregate in the way you want. In the case I placed above, you're only looping through the unique values in your list and using the native sum() or average() functions on the corresponding values. 

    If your data is in a database table then you can easily use a!queryEntity or a!queryRecordType to aggregate the data on query.

    How is your data getting into your SAIL interface? If it's from a query, then simply update that query to use a queryAggregation

  • 0
    Certified Senior Developer
    in reply to Danny Verb

    Ok I understand, thank you for the explanation.

    But your previous code will be perfect for what I need.

  • 0
    Certified Senior Developer
    in reply to cedric01

    Danny, this time how would you do the Qty sum on 2 disctinct field values (Type1 et Type2) ?  (without any SQL of course)

  • a!localVariables(
      local!myData: {
        a!map(id: 1, type1: 1, type2: 12, value: 10),
        a!map(id: 2, type1: 1, type2: 12, value: 15),
        a!map(id: 3, type1: 1, type2: 25, value: 20),
        a!map(id: 4, type1: 1, type2: 12, value: 25),
        a!map(id: 5, type1: 2, type2: 30, value: 5),
        a!map(id: 6, type1: 2, type2: 30, value: 15),
        a!map(id: 7, type1: 2, type2: 12, value: 15),
        a!map(id: 8, type1: 2, type2: 12, value: 22)
      },
      local!uniqueTypesParent: union(local!myData.type1, local!myData.type1),
      local!aggregateValues: a!flatten(
        a!forEach(
          items: local!uniqueTypesParent,
          expression: a!localVariables(
            local!parent: fv!item,
            local!subsetData: index(
              local!myData,
              wherecontains(
                tointeger(local!parent),
                tointeger(local!myData.type1)
              ),
              {}
            ),
            local!uniqueTypesChild: union(
              local!subsetData.type2,
              local!subsetData.type2
            ),
            a!forEach(
              items: local!uniqueTypesChild,
              expression: a!map(
                id: fv!index,
                type1: local!parent,
                type2: fv!item,
                value: sum(
                  index(
                    local!subsetData.value,
                    wherecontains(
                      tointeger(fv!item),
                      tointeger(local!subsetData.type2)
                    ),
                    {}
                  )
                )
              )
            )
          )
        )
      ),
      a!update(
        data: local!aggregateValues,
        index: "id",
        value: 1 + enumerate(length(local!aggregateValues))
      )
    )

  • 0
    Certified Senior Developer
    in reply to Siddharth

    Thanks a lot , but it seems the index is incorrect.

    Your code generates : 1,2,1,2,1,2  (but 1,2,3,4,5,6 expected)

  • It does generate the correct index values (the a!update at line 51 has been used for generating the correct 'id' values). Can you please double check.

  • 0
    Certified Senior Developer
    in reply to Siddharth

    Thank you Siddharth,

    Sorry, the index is not a problem, and I finally need more to get the id (or list of ids) than the index.

    I've created another example with an addional level (I have now : Type, SubType ans SubType2).

    All seems to work well but I have met a special case.

    Here is the example and code below.

    Could you tell me why I am obtaining this 5th line please ? (here is my code below)

       

      local!aggregateValues: a!flatten(
        a!forEach(
          items: local!uniqueTypesParent,
          expression: a!localVariables(
            local!parent: fv!item,
            local!subsetData: index(
              local!vehicles,
              wherecontains(
                tointeger(local!parent),
                tointeger(local!vehicles.typeid)
              ),
              {}
            ),
            local!uniqueSubTypesChild: union(
              local!subsetData.subtypeid,
              local!subsetData.subtypeid
            ),
            a!forEach(
              items: local!uniqueSubTypesChild,
              expression: a!localVariables(
                local!parent1: fv!item,
                local!subsetData1: index(
                  local!vehicles,
                  wherecontains(
                    tointeger(local!parent1),
                    tointeger(local!vehicles.subtypeid)
                  ),
                  {}
                ),
                local!uniqueSubTypesChild2: union(
                  local!subsetData1.subtypeid2,
                  local!subsetData1.subtypeid2
                ),
                a!forEach(
                  items: local!uniqueSubTypesChild2,
                  expression: a!map(
                    id: a!localVariables(
                      local!listeTypes: index(
                        local!vehicles,
                        wherecontains(local!parent, local!vehicles.typeid)
                      ),
                      local!listeSubTypes: index(
                        local!listeTypes,
                        wherecontains(local!parent1, local!listeTypes.subtypeid)
                      ),
                      local!listeSubTypes2: index(
                        local!listeSubTypes,
                        wherecontains(fv!item, local!listeSubTypes.subtypeid2)
                      ),
                      local!listeSubTypes2.id
                    ),
                    typeid: local!parent,
                    subtypeid: local!parent1,
                    subtypeid2: fv!item,
                    value: sum(
                      index(
                        local!subsetData.value,
                        wherecontains(
                          tointeger(fv!item),
                          tointeger(local!subsetData.subtypeid2)
                        ),
                        {}
                      )
                    )
                  )
                )
              )
            )
          )
        )
      ), 

  • 0
    Certified Senior Developer
    in reply to cedric01

    no idea for my last example ?