fbpx

Group By

GROUP BY

GROUP BY allows users to apply other aggregate functions to sub-sets of the set of entities matching the query.

This is the fundamental building block for analyzing information by Type, Status, Priority etc.

Syntax

GROUP BY <FieldSelector> [AS "Alias"] { <AggregationFunction1>, <AggregationFunction2> ... } AS "Alias"

The “FieldSelector” can currently be either a field name e.g.

GROUP BY Status { COUNT }

Which would display results like this:

Or can be a function call:

GROUP BY Fill(Status) { COUNT }

Which in this case would fill out the results to include all possible values (not just values included in the result of the query).

In the above GROUP BY statement, the function “Fill” will expand the GROUP BY to include all values from the Status picklist (which means the results will include 0-counts/0-sums).

Functions

Fill

The Fill function takes a single argument, the name of the field to GROUP BY. It will expand the results to include all groups, not just the groups which include 1 or more matches within the query.

Example:

GROUP BY Fill(Priority) { COUNT }

Month

The Month function takes at least one argument, the name of the field to GROUP BY. The field must be a date/time field. It will group the results based on the Month of the date supplied (all results will be grouped by the first day of the month they belong to).
Optionally, it can also include a Format and/or Range function (see the Format and Range functions below).

Example:

GROUP BY Month(CreatedAt) { COUNT }

This above aggregation would display results grouped by the first day of each month, as shown in this screen shot:

Day

The Day function takes at least one argument, the name of the field to GROUP BY. The field must be a date/time field. It will group the results based on the day of the date supplied (all results will be grouped by the day of the year they belong to, regardless of time). Optionally, it can also include a Format and/or Range function (see the Format and Range functions below).

Example:

GROUP BY Day(LastUpdatedAt) { COUNT } WHERE LastUpdatedAt >= DateSubtract(Now(), "2 weeks")

Note: When executing group by queries, results will be confined to only those days included in the result set:

To return the empty days as well, across a date range, use the “Range” function (see below for more details):

Year

The Year function takes at least one argument, the name of the field to GROUP BY. The field must be a date/time field. It will group the results based on the year of the date supplied (all results will be grouped by the year they belong to). Optionally, it can also include a Format and/or Range function (see the Format and Range functions below).

Example:

GROUP BY Year(CreatedAt) { COUNT }

Quarter

The Quarter function takes at least one argument, the name of the field to GROUP BY. The field must be a date/time field. It will group the results based on the quarter of the year they belong to. Optionally, it can also include a Format and/or Range function (see the Format and Range functions below).

Example:

GROUP BY Quarter(CreatedAt) {
    GROUP BY Project {
        COUNT
    }
}

Format

The Format function is a second-level function that can be passed to the various “Date” functions (Month, Day, Year & Quarter). It will be used to format the value of the date for display purposes – this allows you to convert the value in a more friendly format (so for example when grouping by month, you might want to output the date as “June – 2011”, instead of the default “2011-06-01”.

The format strings correspond to the Microsoft .Net Date/Time format strings, as documented here.

Note: The resulting string must be unique from all other group values strings, so for example if grouping by day, you could not provide a format string that only includes the year, as this would result in non-unique group names.

Example:

GROUP BY Year(CreatedAt, Format("yyyy")) { COUNT } WHERE EntityType = Requirement

Range

By default the values will range from the natural start and end date of the results, but in some cases you may wish to extend the range further for the purposes of reporting (for example if you want to have the range include particular start and end dates).

Range takes 2 arguments, both date/time values, being the start and end dates of the range.

Example:

GROUP BY Day(LastUpdatedAt, Range('2011-1-1','2012-1-1')) { COUNT } WHERE Project = 'Project X' AND EntityType = Requirement

Examples

GROUP BY packages to find when the first script assignment was created, and the last script assignment was updated (to see where activity in the project is occurring).

GROUP BY Package { Min(CreatedAt) AS "First Activity", Max(LastUpdatedAt) AS "Last Activity", COUNT AS "Total"} AS "Package" WHERE Project = "Project X" AND EntityType = ScriptAssignment

A variation on the previous example, using the full path of the packages, as opposed to just the package name:

GROUP BY PackagePath {
    Min(CreatedAt) AS "First Activity",
    Max(LastUpdatedAt) AS "Last Activity",
    COUNT AS "Total"
} AS "Package"
WHERE Project = "Project X" AND EntityType = ScriptAssignment

Here is how the output for the above query would look:

Find the number of entities being created per month over the last 3 years:

GROUP BY Month(CreatedAt, RANGE('2010-1-1', '2012-1-1'), Format('MMMM yyyy')) { COUNT }

The above example will GROUP BY date with labels like “January 2010” etc.

Below is an example of nested GROUP BY aggregations – this example gives a break down of each incident, by component, then type and finally priority, where the status is “Open” or “Reopened”

GROUP BY Component {
  GROUP BY Type {
    GROUP BY Priority {
      COUNT
    }
  }
}  
WHERE Status = Open

The above query would return results like this, using nested tree nodes:

Note: Though we display the above query over multiple lines (for clarity), this is entirely optional and nested GROUP BY’s can all appear on a single line. Because pressing enter while typing executes the query, you need to hold the “SHIFT” key while pressing enter to move the cursor to the next line of the text editor.

Facet Functions

Facet Functions

Facets use functions to determine which values will be matched against each facet. A list of the available functions is below:

Note: some functions will not return true/false values, and those can only be composed together as values passed to other functions when constructing faceted queries.

Function: AndArgs

Syntax

AndArgs(arg1,arg2... argN)

Description

AndArgs will take two or more arguments, and return true, if all the arguments are also true.

AndArgs is useful to combine the results of two or more comparison functions together.

Examples

Where Status is Draft and Type is Bug:

Faceted AndArgs(Equal(Status,Open), Equal(Type,Bug)) AS "Open Bugs" { COUNT } WHERE EntityType = Incident

Where Type is Epic and HasCoverage is true:

Faceted AndArgs(Equal(Type,Epic), Equal(HasCoverage, Yes)) AS "Epics with Coverage" { COUNT } WHERE EntityType = Requirement

Function: DateAdd

Syntax

DateAdd(<FieldName|Function>, <timespan>)

Description

DateAdd allows you to add time to a date value, this can be used to modify values passed to the comparison functions such as GreaterThan

The TimeSpan can be in one of the following formats:

  • hh:mm:ss i.e. 5 minutes would be “00:05:00”
  • N w(eeks), N d(ays), N h(ours), N m(inutes) i.e. “2 weeks”, “2d 4h”, “5 minutes”, “5m” are all valid values.

Examples

Everything where the item was created more than 2 weeks before its last update:

Faceted GreaterThan(LastUpdatedAt, DateAdd(CreatedAt, 2w)) { COUNT } WHERE EntityType = Script

Function: DateSubtract

Syntax

DateSubtract(<FieldName|Function>, <timespan>)

Description

DateSubtract allows you to add time to a date value, this can be used to modify values passed to the comparison functions such as GreaterThan

The TimeSpan can be in one of the following formats:

  • hh:mm:ss i.e. 5 minutes would be “00:05:00”
  • N w(eeks), N d(ays), N h(ours), N m(inutes) i.e. “2 weeks”, “2d 4h”, “5 minutes”, “5m” are all valid values.

Examples

Everything where the item was created more then 2 weeks before its last update:

Faceted LessThan(CreatedAt, DateSubtract(LastUpdatedAt, 2w)) { COUNT } WHERE EntityType = Script

Function: Equal

Syntax

Equal(<FieldName|Function>, <Value|Function>)

Description

Equal allows you to compare the value of a field or function to a fixed value, another field or a function.

It will return true if the first parameter is equal to the second parameter.

Examples

Priority high:

Faceted Equal(Priority,High) { COUNT } WHERE EntityType = Requirement

EstimatedDuration is equal to 5 minutes:

Faceted Equal(EstimatedDuration, '5 minutes') { COUNT } WHERE EntityType = Script

CreatedAt date/time is equal to the LastUpdatedAt date/time:

Function: Field

Syntax

Field(fieldName)

Description

Field takes a single string argument and returns the value of the field. This function is normally implicitly declared when using comparison functions such as Equal, so for example this:

Equal(Priority,High)

Automatically becomes this during query compilation:

Equal(Field(Priority), High)

Field is useful when passing values to non-comparison functions, such as DateAdd, DateSubtract etc. or when comparing one field to another.

Examples

Count of items where the DueDate (custom date field) is after the last updated date:

Faceted GreaterThan(DueDate, Field(LastUpdatedAt)) AS "Changed after due" { COUNT } WHERE EntityType = Incident

Function: GreaterThan

Syntax

GreaterThan(<FieldName|Function>, <Value|Function>)

Description

Greater than allows you to compare the value of a field or function to a fixed value, another field or a function.

It will return true if the first parameter is greater than the second parameter.

Examples

Average duration of scripts with more than 10 steps:

Faceted GreaterThan(ScriptStepCount,10) { Average(EstimatedDuration) } WHERE EntityType = Script

EstimatedDuration is greater than 5 minutes:

Faceted GreaterThan(EstimatedDuration, '5 minutes') { COUNT } WHERE EntityType = Script

Script assignments where the last run has an actual duration that is greater than the estimated duration for the associated script:

Faceted GreaterThan(ActualDuration, Field(EstimatedDuration)) { COUNT } WHERE EntityType = ScriptAssignment

Function: GreaterThanOrEqual

Syntax

GreaterThanOrEqual(<FieldName|Function>, <Value|Function>)

Description

The GreaterThanOrEqual function allows you to compare the value of a field or function to a fixed value, another field or a function.

It will return true if the first parameter is greater than or equal in value to the second parameter.

Examples

Average duration of scripts with 10 or more steps:

Faceted GreaterThanOrEqual(ScriptStepCount,10) { Average(EstimatedDuration) } WHERE EntityType = Script

EstimatedDuration is greater than or equal to 10 minutes:

Faceted GreaterThanOrEqual(EstimatedDuration, '10 minutes') { COUNT } WHERE EntityType = Script

Script assignments where the last run has an actual duration that is equal to or greater to the estimated duration for the associated script:

Faceted GreaterThanOrEqual(ActualDuration, Field(EstimatedDuration)) { COUNT } WHERE EntityType = ScriptAssignment

Function: IsNot

Syntax

IsNot(function)

Description

The IsNot function takes a single parameter, which should be a function that returns a boolean (true/false) value. If the function returns true, IsNot will return false and if the return value is false, IsNot will return true.

Examples

Any scripts where the step count is NOT between 10 and 20:

Faceted IsNot(Range(ScriptStepCount,10,20)) { COUNT } WHERE EntityType = Script

Function: LessThan

Syntax

LessThan(<FieldName|Function>, <Value|Function>)

Description

The LessThan function allows you to compare the value of a field or function to a fixed value, another field or a function.

It will return true if the first parameter is less than the second parameter.

Examples

Average duration of scripts with less than 20 steps:

Faceted LessThan(ScriptStepCount,20) { Average(EstimatedDuration) } WHERE EntityType = Script

EstimatedDuration is less than 5 minutes:

Faceted LessThan(EstimatedDuration, '5 minutes') { COUNT } WHERE EntityType = Script

Script assignments where the last run has an actual duration that is less than the estimated duration for the associated script:

Faceted LessThan(ActualDuration, Field(EstimatedDuration)) { COUNT } WHERE EntityType = ScriptAssignment

Function: LessThanOrEqual

Syntax

LessThanOrEqual(<FieldName|Function>, <Value|Function>)

Description

The LessThanOrEqual function allows you to compare the value of a field or function to a fixed value, another field or a function.

It will return true if the first parameter is less than or equal to the second parameter.

Examples

Average duration of scripts with less than or equal to 30 steps:

Faceted LessThanOrEqual(ScriptStepCount,30) { Average(EstimatedDuration) } WHERE EntityType = Script

EstimatedDuration is less than or equal to 5 minutes:

Faceted LessThanOrEqual(EstimatedDuration, '5 minutes') { COUNT } WHERE EntityType = Script

Script assignments where the last run has an actual duration that is less than or equal to the estimated duration for the associated script:

Faceted LessThanOrEqual(ActualDuration, Field(EstimatedDuration)) { COUNT } WHERE EntityType = ScriptAssignment

Function: NotEqual

Syntax

NotEqual(<FieldName|Function>, <Value|Function>)

Description

Not Equal allows you to compare the value of a field or function to a fixed value, another field or a function.

It will return true if the first parameter is not equal to the second parameter.

Examples

Priority is not low:

Faceted NotEqual(Priority,Low) { COUNT } WHERE EntityType = Requirement

EstimatedDuration is not equal to 15 minutes:

Faceted NotEqual(EstimatedDuration,'15 minutes') { COUNT } WHERE EntityType = TestScript

CreatedAt date/time is not equal to the LastUpdatedAt date/time:

Faceted NotEqual(CreatedAt, Field(LastUpdatedAt)) { COUNT } WHERE EntityType = TestScript

Function: Now

Syntax

Now()

Description

Now returns the current date and time.

Examples

All scripts where the script was created more than 2 weeks before today:

Faceted LessThan(CreatedAt, DateSubtract(Now(), 2w)) { COUNT } WHERE EntityType = Script

Function: OrArgs

Syntax

OrArgs(arg1,arg2... argN)

Description

OrArgs will take two or more arguments, and return true, if any of the arguments passed to it are true.

OrArgs is useful to combine the results of two or more comparison functions together.

Examples

Where Priority is High, or the Custom Field ‘Severity’ is High:

Faceted OrArgs(Equal(Priority,High), Equal(Severity,High)) AS "Urgent" { COUNT } WHERE EntityType = Incident

Where Type is ‘Non Functional’ or item has no coverage:

Faceted OrArgs(Equal(Type,'Non Functional'), Equal(HasCoverage,No)) AS "Non Function or Uncovered" { COUNT } WHERE EntityType = Requirement

Function: Range

Syntax

Range(<FieldName|Function>, start, end)

Description

Range allows you to compare a field or the result of a function to a start and end value.

It will return true if the first parameter’s value falls within the start and end values of the range.

Examples

Average estimated duration of scripts with between 10 and 20 steps:

Faceted Range(ScriptStepCount,10,20) { Average(EstimatedDuration) } WHERE EntityType = Script

Count of steps with an EstimatedDuration between 10 and 30 minutes:

Faceted Range(EstimatedDuration, '10m','30m') { COUNT } WHERE EntityType = Script

Function: Today

Syntax

Today()

Description

Today returns the todays date with no time component (i.e. the very start of today)

Examples

All scripts that were updated today:

Faceted GreaterThanOrEqual(LastUpdatedAt, Today()) { COUNT } WHERE EntityType = Script

Function: Unmatched

Syntax

Unmatched()

Description

Unmatched is a special function which returns true if the value has not matched any of the previous facets, it does not accept any arguments.

To illustrate – if there were 3 requirements, each with different priorities:

  • Requirement A – Priority: High
  • Requirement B – Priority: Low
  • Requirement C – Priority: Medium

We could write a faceted aggregation expression:

Faceted Equal(Priority, High) AS 'Urgent',
        OrArgs(Equal(Priority, Low), Equal(Priority, Medium)) AS 'Non-Urgent'
{
   COUNT
}
WHERE EntityType = Requirement

But if we add more non-high priorities to the picklist over time, we will need to update our faceted query to then capture those values.

As an alternative we could just write this:

Faceted Equal(Priority,High) as 'Urgent',
        Unmatched() as 'Non-Urgent'
{
   COUNT
}
WHERE EntityType = Requirement

In this case, anything that doesn’t match urgent will be “unmatched” and fall through to the “Unmatched()” facet.

Function: Yesterday

Syntax

Yesterday()

Description

Yesterday returns the previous day’s date with no time component.

Examples

All scripts where the script was created before yesterday:

Faceted LessThan(CreatedAt, Yesterday()) { COUNT } WHERE EntityType = Script

Faceted

Faceted

A faceted query allows you to specify groups/categories in which results will be matched and collected.

Overview

In a GROUP BY aggregation, results are grouped based on the value of a field within each result. In contrast the “Faceted” aggregation allows the user to provide the name and criteria for each group known as a “facet”.

Note: a single result can be collected into more than one group, where as a GROUP BY is guaranteed to collect each result into only one of the possible groups (values) for that field (except in the case of multi-select fields such as Components, Fixed/Affected versions etc.)

Facets should be familiar to anyone who has shopped online, where you will often see items divided in arbitrary groups which make it easer to find what you are looking for, i.e.

  • $10 and less
  • $10 to $50
  • $50 or more
  • On Special

Being able to break information down into meaningful ranges is a powerful tool which allows test managers to easily get an overview of the status of testing, and the quality/makeup of their test artifacts.

Examples

If you have a set of data with three distinct statuses:

  • Draft
  • Approved
  • Out Of Date

You could get a count of each type by using this GROUP BY query:

GROUP BY Status { COUNT }

But, what if you just want two counts, one for approved, and the other for both “Draft” and “Out of Date”?

This is where Faceted queries come in handy:

FACETED Equal(Status,Approved) as "Approved",
        OrArgs(Equal(Status,Draft), Equal(Status,'Out Of Date')) AS "Not Approved"
{
    COUNT
}

In the above query we are creating two “Facets” – the first facet for all matches where the Status is “Approved”, and the second which matches any status which is “Draft” or “Out Of Date”, and for each we calculate the count.

In the above example, we could also simplify it by counting everything that didn’t match the first facets predicate to be counted as the second facet, by using the Unmatched() function:

FACETED Equal(Status,Approved) as "Approved",
        Unmatched() AS "Not Approved"
{
    COUNT
}

In the above example we are only showing two facets – but the number of facets you can define is unlimited – each facet just needs to be separated by a comma – and at the end of the list of facets you must define a set of aggregate functions to be executed for each facet, just as you would when writing a GROUP BY query.

Here is an example of the output you would expect from the above example:

Syntax

Faceted aggregations use the following syntax:

FACETED [Facet1],[Facet2],[FacetN] { Aggregation1, Aggregation2.. AggregationN }

Each Facet is a function call with an optional alias (which must be provided in quotes):

<Function Call> [AS "Alias"|AS 'Alias']

If you do not supply an alias, the function call itself followed by the word “Facet” will be used as the name of this facet.

Functions

For a list of supported functions within a Facet, see the Facet Functions topic.

Entities

Entities

Overview

Aggregations are useful for collecting summary information across large sets of data, but in some cases you may wish to retrieve the names & ID’s of those entities which matched each group or facet. In these cases the “Entities” aggregate function can be used.

Syntax

Plain form:

Entities

Form with a set limit of results per node (if no value supplied, it will default to 50):

Entities(20)

Form which will return any number of results:

Entities(Max)

Note: Be careful when using this option, it is not a good idea unless you absolutely need all the results, because results are not fetched in pages.

These queries may take a long time to execution when there is a large amount of data.

Examples

Group by the status of all entities in a particular project, displaying the entities matching each status:

GROUP BY Status { Entities } WHERE Project = 'Project X'

Here is the output of executing the above query:

Note: Nodes can be clicked on to view the associated record, and hovering over the node will show the Type, Name and ID of that node.

Count

Count

Count is the simplest of aggregate functions, and will just return the count of matching entities.

Examples

Count all records in Enterprise Tester

Count

Count all records in a project

Count WHERE Project = 'Project X'

Count all incidents in a project with a status of “Open”

COUNT WHERE Project = 'Project X' AND EntityType = Incident AND Status = Open

Count all incidents, grouped by their status

GROUP BY Status { COUNT } WHERE Project = 'Project X' AND EntityType = Incident

AVG (Average)

AVG (Average)

Syntax

The AVG function can be used on any fields supporting aggregation which have a numeric type:

  • TimeSpan
  • DateTime
  • Integer (Int32/Int64)
  • Double
  • Float
  • Decimal

It will return the average value across all the values in the query (or the set of values being evaluated for the current Facet or Group).

Examples

This example would return the average number of steps for each script in a project.

AVG(ScriptStepCount) WHERE EntityType = Script

This would return the average time taken to execute scripts within a project (which have an actual duration recorded).

AVG(ActualDuration) AS "Actual", AVG(EstimatedDuration) AS "Estimated"
WHERE EntityType = Script AND ActualDuration IS NOT Empty

This would return the average number of incidents raised per test script assignment, grouped by the type of the associated script.

GROUP BY ScriptType { AVG(IncidentCount) AS 'Average' } AS 'Types'
WHERE EntityType = ScriptAssignment