Aggregating data in query objects
In a query object, you can use the Method property to do a calculation on the fields of a column and return the calculated value in the dataset. For example, you can sum all the fields in a column or find the average value. The Method
property is set on column
controls and can be set to any of the following aggregate methods.
Aggregate method | Description |
---|---|
Sum | Calculates the sum of the values of the field in the designated column for all records that are selected as part of the grouped set. |
Average | Calculates the average value of the field in the designated column for all records that are selected as part of the grouped set. When averaging fields that have an integer data type (such as Integer or BigInteger ), integer division is used. The result isn't rounded, and the remainder is discarded. For example, 5รท2=2 instead of 2.5 (or 2 1/2). |
Min | Retrieves the lowest value of the field in the designated column for all records that are selected as part of the grouped set. |
Max | Retrieves the highest value of the field in the designated column for all records that are selected as part of the grouped set. |
Count | Returns the number of records that are selected as part of the grouped set. You can return a set of Distinct values from a table using a Count method. |
Setting up an aggregate method for a query column
Except for the Count
method, you can only use an aggregate method (Sum
, Average
, Min
, and Max
) on a field that has a numeric data type of Decimal, Integer, BigInteger, or Duration. To set up an aggregate on a column, you set the column's Method Property.
column(Name; Field)
{
Method = Sum|Average|Min|Max|Count;
}
Setting an aggregate method on a column will automatically group the resultant data set by the other columns in the query. Records that have matching values for the other columns are grouped together into a single row in the results. The aggregate method is then applied against the group and a summary value returned in the row. It's similar to the GROUP BY clause in SQL SELECT statements.
The aggregate methods and grouping are further explained in the following sections.
Sample Query
The following sample query object retrieves the number of line items in every sales order for each customer. The query links the Customer table and the Sales Line table. In its current state, the Method
property is commented out so it doesn't implement any aggregate method.
query 50101 "Customer_Sales_Quantity"
{
QueryType = Normal;
// Sorts the results in descending order
OrderBy = descending(Qty);
elements
{
dataitem(C; Customer)
{
column(Customer_Number; "No.")
{
}
column(Customer_Name; Name)
{
}
dataitem(SL; "Sales Line")
{
DataItemLink = "Sell-to Customer No." = c."No.";
SqlJoinType = InnerJoin;
column(Qty; Quantity)
{
// Change the value of the property to perform a different aggregate method on grouped columns:
// Sum, Average, Max, Min, or Count
// Method = Sum|Average|Min|Max|Count;
}
}
}
}
}
The following table represents a simplified version of the resulting dataset for the sample query.
Customer_Number | Customer_Name | Qty |
---|---|---|
20000 | Selangorian Ltd. | 400 |
30000 | Blanemark Hifi | 350 |
20000 | Selangorian Ltd. | 300 |
40000 | Deerfield Graphics | 250 |
20000 | Selangorian Ltd. | 200 |
30000 | Blanemark Hifi | 150 |
The following sections explain how you can modify the query to implement the different aggregate methods by changing the value of the Method property.
Sum
The Sum
method adds the values of all fields for the specified column within a group. To set up a Sum
method on the Quantity column of the sample query, set the Method
property to Sum
. The query is automatically grouped by the No. and Name columns.
...
column(Qty; Quantity)
{
Method = Sum;
}
...
Looking at the sample query, you can use Sum
method to get the total number of items in sales orders for each customer. The following table illustrates the resulting dataset for the query.
Customer_Number | Customer_Name | Qty |
---|---|---|
20000 | Selangorian Ltd. | 900 |
30000 | Blanemark Hifi | 500 |
40000 | Deerfield Graphics | 250 |
Average
The Average
method calculates the average value of the fields in the column within a group. To set up an Average method on the Quantity column of the sample query, set the Method
property to Average
. The query is automatically grouped by the No. and Name columns:
...
column(Qty; Quantity)
{
Method = Average;
}
...
Looking at the sample query, you can use Average
method to get the average number of items in sales orders for each customer. The following table illustrates the resulting dataset for the query.
Customer_Number | Customer_Name | Qty |
---|---|---|
20000 | Selangorian Ltd. | 300 |
30000 | Blanemark Hifi | 250 |
40000 | Deerfield Graphics | 250 |
Min
The Min
method retrieves the lowest value of fields in the column within a group. To set up a Min
method on the Quantity column of the sample query, set the Method
property to Min
. The name of the Quantity column automatically changes to Min_Quantity and the query is automatically grouped by the No. and Name columns:
...
column(Qty; Quantity)
{
Method = Min;
}
...
Looking at the sample query, you can use Min
method to get the least number of items in sales orders for each customer. The following table illustrates the resulting dataset for the query.
Customer_Number | Customer_Name | Qty |
---|---|---|
40000 | Deerfield Graphics | 250 |
20000 | Selangorian Ltd. | 200 |
30000 | Blanemark Hifi | 150 |
Max
The Max
method retrieves the highest value of fields in the column within a group. To set up a Max
method on the Quantity column of the sample query, set the Method
property to Max
. The name of the Quantity column automatically changes to Max_Quantity and the query is automatically grouped by the No. and Name columns:
...
column(Qty; Quantity)
{
Method = Max;
}
...
Looking at the sample query, you can use Max
method to get the greatest number of items in sales orders for each customer. The following table illustrates the resulting dataset for the query.
Customer_Number | Customer_Name | Qty |
---|---|---|
20000 | Selangorian Ltd. | 400 |
30000 | Blanemark Hifi | 350 |
40000 | Deerfield Graphics | 250 |
Count
The Count
method returns the number of records from the data item table that comprise a group in the dataset. Unlike the other aggregate methods, the Count
method is not associated with a specific column. Records are identified and counted based on the primary key of the data item table. Referring to the sample query, you can use a Count
method to get the number of open sales orders per customer.
To set up a Count
method in the sample query, the column
element definition cannot include a source table; only a name. Therefore, you can delete the reference to the Quantity
field in the column(Qty; Quantity)
element and set the Method
property to Count
:
...
column(Qty)
{
Method = Count;
}
Looking at the sample query, you can use Count
method the number of sales orders for each customer. The following table illustrates the resulting dataset for the query.
Customer_Number | Customer_Name | Qty |
---|---|---|
20000 | Selangorian Ltd. | 3 |
30000 | Blanemark Hifi | 2 |
40000 | Deerfield Graphics | 1 |
In SQL SELECT statements, the Count method corresponds to a COUNT(*) or COUNT(field) clause.
Using a query to get distinct values
When working with table data, you might need to get a list of distinct values from the table (in SQL, this would correspond to a SELECT DISTINCT statement). This operation isn't supported out-of-the-box in AL, but you can do it with a query using an aggregation.
This AL example code shows how you can encode distinct into a query using an aggregation.
query 50150 DistinctValuesQuery
{
Caption = 'My Query';
QueryType = Normal;
elements
{
dataitem(CustLedgerEntry; "Cust. Ledger Entry")
{
column(CustomerNo; "Customer No.")
{
}
column(DocumentType; "Document Type")
{
}
column(Count)
{
Method = Count;
}
}
}
}
This AL example code shows how you can then query for the distinct values (note that the Count
column isn't used here).
trigger OnAction()
var
MyQuery: Query DistinctValuesQuery;
CombinationText: Text;
begin
if MyQuery.Open() then begin
while MyQuery.Read() do
CombinationText += MyQuery.CustomerNo + '-' + Format(MyQuery.DocumentType) + '; ';
MyQuery.Close();
end;
Message(CombinationText);
end;
Contributors
This article is maintained by Microsoft. Parts of the examples were originally written by the following contributor.
- Teddy Herryanto | Business Central Techno Functional Consultant
See Also
Method Property
Query Object
Filtering Queries
Aggregating Data
Aggregate Functions (Transact-SQL)