# Post Aggregators

Post-aggregations are specifications of processing that should happen on aggregated values as they come out of the timeseries DB.

## Field accessor post-aggregator

These post-aggregators return the value produced by the specified aggregator. Use type "field object, or use type “finalizingFieldAccess” to return a finalized value, such as an estimated cardinality.

``{ "type": "fieldAccess", "name": "tot", "fieldName": "tot" }``

## Constant post-aggregator

The constant post-aggregator always returns the specified value.

``{ "type": "constant", "name": "const", "value": 100 }``

## Arithmetic post-aggregator

The arithmetic post-aggregator applies the provided function to the given fields from left to right. The Supported functions are `+`, `-`, `*`, `/`, and `quotient`.

Note:

• / division always returns 0 if dividing by 0, regardless of the numerator.
• quotient division behaves like regular floating point division
• Arithmetic post-aggregators always use floating point arithmetic.
• Arithmetic post-aggregators may also specify an ordering, which defines the order of resulting values when sorting.
• If no ordering (or null) is specified, the default floating point ordering is used.
• numericFirst ordering always returns finite values first, followed by NaN, and infinite values last.
``````{
"type": "arithmetic",
"name": "part_percentage",
"fn": "*",
"fields": [
{
"type": "arithmetic",
"name": "ratio",
"fn": "/",
"fields": [
{ "type": "fieldAccess", "name": "part", "fieldName": "part" },
{ "type": "fieldAccess", "name": "tot", "fieldName": "tot" }
]
},
{ "type": "constant", "name": "const", "value": 100 }
]
}``````

## Expression post-aggregator

The expression post-aggregator is defined using a Druid expression.

``````{
"type": "expression",
"name": "part_percentage",
"expression": "100 * (part / tot)"
}``````

## HyperUnique Cardinality post-aggregator

The hyperUniqueCardinality post aggregator is used to wrap a hyperUnique object such that it can be used in post aggregations.

``````{
"type": "arithmetic",
"name": "average_users_per_row",
"fn": "/",
"fields": [
{ "type": "hyperUniqueCardinality", "fieldName": "unique_users" },
{ "type": "fieldAccess", "name": "rows", "fieldName": "rows" }
]
}``````

## Theta Sketch Estimate post-aggregator

The thetaSketchEstimate post aggregator is used to wrap a theta sketch object such that it can be used in post aggregations.

This is used in the following example to compute the number of users who launched the app and then entered data.

``````{
"name": "app_launched_and_data_entered_count",
"field": {
"name": "app_launched_and_data_entered_count",
"func": "INTERSECT",
"fields": [
{
"type": "fieldAccess",
},
{
"type": "fieldAccess",
"fieldName": "dataEntered_count"
}
]
}
}``````

## Theta Sketch Set Operation post-aggregator

The thetaSketchSetOp post aggregator is used to wrap a theta sketch object such that it can be used in post aggregations.

This is used in the following example to compute the number of users who launched the app and then entered data.

``````{
"name": "app_launched_and_data_entered_count",
"field": {
"name": "app_launched_and_data_entered_count",
"func": "INTERSECT",
"fields": [
{
"type": "fieldAccess",
},
{
"type": "fieldAccess",
"fieldName": "dataEntered_count"
}
]
}
}``````

## Greatest / Least post-aggregators

`doubleGreatest` computes the maximum of all fields and `Double.NEGATIVE_INFINITY`. `doubleLeast` computes the minimum of all fields and `Double.POSITIVE_INFINITY.`

The difference between the doubleMax aggregator and the doubleGreatest post-aggregator is that doubleMax returns the highest value of all rows for one specific column while doubleGreatest returns the highest value of multiple columns in one row. These are similar to the SQL MAX and GREATEST functions.

Example:

``````{
"type" : "doubleGreatest",
"name" : <output_name>,
"fields": [<post_aggregator>, <post_aggregator>, ...]
}``````
{"ft_lang_label":"__label__en","ft_lang_prob":0.7210862,"math_prob":0.6629794,"size":4024,"snap":"2023-40-2023-50","text_gpt3_token_len":958,"char_repetition_ratio":0.17810945,"word_repetition_ratio":0.3126177,"special_character_ratio":0.25894633,"punctuation_ratio":0.23211446,"nsfw_num_words":0,"has_unicode_error":false,"math_prob_llama3":0.9659204,"pos_list":[0],"im_url_duplicate_count":[null],"WARC_HEADER":"{\"WARC-Type\":\"response\",\"WARC-Date\":\"2023-09-30T09:05:56Z\",\"WARC-Record-ID\":\"<urn:uuid:a9167ebf-390a-4874-916a-694274ea2763>\",\"Content-Length\":\"54565\",\"Content-Type\":\"application/http; msgtype=response\",\"WARC-Warcinfo-ID\":\"<urn:uuid:8369bae9-ead7-449a-8eed-83fd0a5b2fb5>\",\"WARC-Concurrent-To\":\"<urn:uuid:2967b509-8458-4c14-9d80-176aa9351b20>\",\"WARC-IP-Address\":\"20.62.72.11\",\"WARC-Target-URI\":\"https://telemetrydeck.com/docs/tql/post-aggregators/\",\"WARC-Payload-Digest\":\"sha1:YQGO2XXFPTBEB22S7TXOUB4DGLXBEENN\",\"WARC-Block-Digest\":\"sha1:LNMUXSNQOCYYR4WVNC26QFGOLY5J3ZW2\",\"WARC-Identified-Payload-Type\":\"text/html\",\"warc_filename\":\"/cc_download/warc_2023/CC-MAIN-2023-40/CC-MAIN-2023-40_segments_1695233510671.0_warc_CC-MAIN-20230930082033-20230930112033-00876.warc.gz\"}"}