Note: The approach you should opt for really depends on how dynamically you want the grouping to be performed. Option 1: Let's say the grouping pattern is always same and there isn't a possibility to change the pattern by applying filters, then include everything in the database view(grouping, counting, percentage calculation) and then just query it in the Appian. Option 2: Provided if the grouping is dynamic (or if you want to use the same view for different purposes where the grouping differs) wherein the user drives it via filters in the report then you may think of doing something as mentioned below. If you carefully observe the below pattern, the expression rule that builds the final data set won't take much time and we are doing it only once and assigning to a label-value pair or a CDT which will help in sorting and also refrain from formatting and calculating on the fly for each row. 1. Build an expression rule which builds the datasubset to be used in the Grid. Name: TEST_buildSLABreachReport Inputs: 1. data (Any Type) Definition: /*You may use a CDT or label value pairs as used below*/ { is_completed_on_time: ri!data.is_completed_on_time, is_sla_breached: ri!data.is_sla_breached, sla_breach_percentage: concat(fixed((ri!data.is_sla_breached/ri!data.vendor)*100,2),"%") } 2. Using the expression rule built above, build the report datasubset that needs to be used in the grid based on the data queried from entity Example: load( local!pagingInfo: a!pagingInfo( startIndex: 1, batchSize: - 1, sort: a!sortInfo( field: "vendor", ascending: true ) ), local!queriedData: a!queryEntity( entity: cons!MY_ENTITY, query: a!query( aggregation: a!queryAggregation( aggregationColumns: { a!queryAggregationColumn( field: "vendor", isGrouping: true ), a!queryAggregationColumn( field: "is_completed_on_time", alias: "is_completed_on_time", aggregationFunction: "SUM" ), a!queryAggregationColumn( field: "is_sla_breached", alias: "is_sla_breached", aggregationFunction: "SUM" ), a!queryAggregationColumn( field: "vendor", alias: "vendor", aggregationFunction: "COUNT" ), } ), logicalExpression: a!queryLogicalExpression( operator: "AND", filters: { a!queryFilter( field: "dateField", operator: "between", value: { date1, date2 } ) } ), pagingInfo: local!pagingInfo ) ), if( local!queriedData.totalCount = 0, todatasubset( {}, local!pagingInfo ), todatasubset( apply( rule!TEST_buildSLABreachReport( data: _ ), local!queriedData.data ), local!pagingInfo ) ) )