"use strict";(self.webpackChunk=self.webpackChunk||[]).push([[405],{28453:(e,n,s)=>{s.d(n,{R:()=>d,x:()=>a});var r=s(96540);const t={},i=r.createContext(t);function d(e){const n=r.useContext(i);return r.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function a(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(t):e.components||t:d(e.components),r.createElement(i.Provider,{value:n},e.children)}},40974:(e,n,s)=>{s.r(n),s.d(n,{assets:()=>o,contentTitle:()=>a,default:()=>h,frontMatter:()=>d,metadata:()=>r,toc:()=>c});const r=JSON.parse('{"id":"querying/post-aggregations","title":"Post-aggregations","description":"\x3c!--","source":"@site/docs/33.0.0/querying/post-aggregations.md","sourceDirName":"querying","slug":"/querying/post-aggregations","permalink":"/docs/33.0.0/querying/post-aggregations","draft":false,"unlisted":false,"tags":[],"version":"current","frontMatter":{"id":"post-aggregations","title":"Post-aggregations"},"sidebar":"docs","previous":{"title":"Aggregations","permalink":"/docs/33.0.0/querying/aggregations"},"next":{"title":"Expressions","permalink":"/docs/33.0.0/querying/math-expr"}}');var t=s(74848),i=s(28453);const d={id:"post-aggregations",title:"Post-aggregations"},a=void 0,o={},c=[{value:"Arithmetic post-aggregator",id:"arithmetic-post-aggregator",level:3},{value:"Field accessor post-aggregators",id:"field-accessor-post-aggregators",level:3},{value:"Constant post-aggregator",id:"constant-post-aggregator",level:3},{value:"Expression post-aggregator",id:"expression-post-aggregator",level:3},{value:"Greatest / Least post-aggregators",id:"greatest--least-post-aggregators",level:3},{value:"JavaScript post-aggregator",id:"javascript-post-aggregator",level:3},{value:"HyperUnique Cardinality post-aggregator",id:"hyperunique-cardinality-post-aggregator",level:3},{value:"Example Usage",id:"example-usage",level:2}];function l(e){const n={a:"a",admonition:"admonition",code:"code",h2:"h2",h3:"h3",li:"li",p:"p",pre:"pre",strong:"strong",table:"table",tbody:"tbody",td:"td",th:"th",thead:"thead",tr:"tr",ul:"ul",...(0,i.R)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(n.admonition,{type:"info",children:(0,t.jsxs)(n.p,{children:["Apache Druid supports two query languages: ",(0,t.jsx)(n.a,{href:"/docs/33.0.0/querying/sql",children:"Druid SQL"})," and ",(0,t.jsx)(n.a,{href:"/docs/33.0.0/querying/",children:"native queries"}),".\nThis document describes the native\nlanguage. For information about functions available in SQL, refer to the\n",(0,t.jsx)(n.a,{href:"/docs/33.0.0/querying/sql-aggregations",children:"SQL documentation"}),"."]})}),"\n",(0,t.jsx)(n.p,{children:"Post-aggregations are specifications of processing that should happen on aggregated values as they come out of Apache Druid. If you include a post aggregation as part of a query, make sure to include all aggregators the post-aggregator requires."}),"\n",(0,t.jsx)(n.p,{children:"There are several post-aggregators available."}),"\n",(0,t.jsx)(n.h3,{id:"arithmetic-post-aggregator",children:"Arithmetic post-aggregator"}),"\n",(0,t.jsx)(n.p,{children:"The arithmetic post-aggregator applies the provided function to the given\nfields from left to right. The fields can be aggregators or other post aggregators."}),"\n",(0,t.jsxs)(n.table,{children:[(0,t.jsx)(n.thead,{children:(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.th,{children:"Property"}),(0,t.jsx)(n.th,{children:"Description"}),(0,t.jsx)(n.th,{children:"Required"})]})}),(0,t.jsxs)(n.tbody,{children:[(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:(0,t.jsx)(n.code,{children:"type"})}),(0,t.jsxs)(n.td,{children:["Must be ",(0,t.jsx)(n.code,{children:'"arithmetic"'}),"."]}),(0,t.jsx)(n.td,{children:"Yes"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:(0,t.jsx)(n.code,{children:"name"})}),(0,t.jsx)(n.td,{children:"Output name of the post-aggregation"}),(0,t.jsx)(n.td,{children:"Yes"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:(0,t.jsx)(n.code,{children:"fn"})}),(0,t.jsxs)(n.td,{children:["Supported functions are ",(0,t.jsx)(n.code,{children:"+"}),", ",(0,t.jsx)(n.code,{children:"-"}),", ",(0,t.jsx)(n.code,{children:"*"}),", ",(0,t.jsx)(n.code,{children:"/"}),", ",(0,t.jsx)(n.code,{children:"pow"})," and ",(0,t.jsx)(n.code,{children:"quotient"})]}),(0,t.jsx)(n.td,{children:"Yes"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:(0,t.jsx)(n.code,{children:"fields"})}),(0,t.jsxs)(n.td,{children:["List of post-aggregator specs which define inputs to the ",(0,t.jsx)(n.code,{children:"fn"})]}),(0,t.jsx)(n.td,{children:"Yes"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:(0,t.jsx)(n.code,{children:"ordering"})}),(0,t.jsxs)(n.td,{children:["If no ordering (or ",(0,t.jsx)(n.code,{children:"null"}),") is specified, the default floating point ordering is used. ",(0,t.jsx)(n.code,{children:"numericFirst"})," ordering always returns finite values first, followed by ",(0,t.jsx)(n.code,{children:"NaN"}),", and infinite values last."]}),(0,t.jsx)(n.td,{children:"No"})]})]})]}),"\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.strong,{children:"Note"}),":"]}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.code,{children:"/"})," division always returns ",(0,t.jsx)(n.code,{children:"0"})," if dividing by",(0,t.jsx)(n.code,{children:"0"}),", regardless of the numerator."]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.code,{children:"quotient"})," division behaves like regular floating point division"]}),"\n",(0,t.jsx)(n.li,{children:"Arithmetic post-aggregators always use floating point arithmetic."}),"\n"]}),"\n",(0,t.jsx)(n.p,{children:"Example:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-json",children:'{\n "type" : "arithmetic",\n "name" : "mult",\n "fn" : "*",\n "fields": [\n {"type": "fieldAccess", "fieldName": "someAgg"},\n {"type": "fieldAccess", "fieldName": "someOtherAgg"}\n ]\n}\n'})}),"\n",(0,t.jsx)(n.h3,{id:"field-accessor-post-aggregators",children:"Field accessor post-aggregators"}),"\n",(0,t.jsxs)(n.p,{children:["These post-aggregators return the value produced by the specified ",(0,t.jsx)(n.a,{href:"/docs/33.0.0/querying/dimensionspecs",children:"dimension"})," or ",(0,t.jsx)(n.a,{href:"/docs/33.0.0/querying/aggregations",children:"aggregator"}),"."]}),"\n",(0,t.jsxs)(n.table,{children:[(0,t.jsx)(n.thead,{children:(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.th,{children:"Property"}),(0,t.jsx)(n.th,{children:"Description"}),(0,t.jsx)(n.th,{children:"Required"})]})}),(0,t.jsxs)(n.tbody,{children:[(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:(0,t.jsx)(n.code,{children:"type"})}),(0,t.jsxs)(n.td,{children:["Must be ",(0,t.jsx)(n.code,{children:'"fieldAccess"'})," or ",(0,t.jsx)(n.code,{children:'"finalizingFieldAccess"'}),". Use type ",(0,t.jsx)(n.code,{children:'"fieldAccess"'})," to return the raw aggregation object, or use type ",(0,t.jsx)(n.code,{children:'"finalizingFieldAccess"'})," to return a finalized value, such as an estimated cardinality."]}),(0,t.jsx)(n.td,{children:"Yes"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:(0,t.jsx)(n.code,{children:"name"})}),(0,t.jsx)(n.td,{children:"Output name of the post-aggregation"}),(0,t.jsxs)(n.td,{children:["Yes if defined as a standalone post-aggregation, but may be omitted if used inline to some other post-aggregator in a ",(0,t.jsx)(n.code,{children:"fields"})," list"]})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:(0,t.jsx)(n.code,{children:"fieldName"})}),(0,t.jsx)(n.td,{children:"The output name of the dimension or aggregator to reference"}),(0,t.jsx)(n.td,{children:"Yes"})]})]})]}),"\n",(0,t.jsx)(n.p,{children:"Example:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-json",children:'{ "type" : "fieldAccess", "name": "someField", "fieldName" : "someAggregator" }\n'})}),"\n",(0,t.jsx)(n.p,{children:"or"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-json",children:'{ "type" : "finalizingFieldAccess", "name": "someFinalizedField", "fieldName" : "someAggregator" }\n'})}),"\n",(0,t.jsx)(n.h3,{id:"constant-post-aggregator",children:"Constant post-aggregator"}),"\n",(0,t.jsx)(n.p,{children:"The constant post-aggregator always returns the specified value."}),"\n",(0,t.jsxs)(n.table,{children:[(0,t.jsx)(n.thead,{children:(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.th,{children:"Property"}),(0,t.jsx)(n.th,{children:"Description"}),(0,t.jsx)(n.th,{children:"Required"})]})}),(0,t.jsxs)(n.tbody,{children:[(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:(0,t.jsx)(n.code,{children:"type"})}),(0,t.jsxs)(n.td,{children:["Must be ",(0,t.jsx)(n.code,{children:'"constant"'})]}),(0,t.jsx)(n.td,{children:"Yes"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:(0,t.jsx)(n.code,{children:"name"})}),(0,t.jsx)(n.td,{children:"Output name of the post-aggregation"}),(0,t.jsx)(n.td,{children:"Yes"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:(0,t.jsx)(n.code,{children:"value"})}),(0,t.jsx)(n.td,{children:"The constant value"}),(0,t.jsx)(n.td,{children:"Yes"})]})]})]}),"\n",(0,t.jsx)(n.p,{children:"Example:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-json",children:'{ "type" : "constant", "name" : "someConstant", "value" : 1234 }\n'})}),"\n",(0,t.jsx)(n.h3,{id:"expression-post-aggregator",children:"Expression post-aggregator"}),"\n",(0,t.jsxs)(n.p,{children:["The expression post-aggregator is defined using a Druid ",(0,t.jsx)(n.a,{href:"/docs/33.0.0/querying/math-expr",children:"expression"}),"."]}),"\n",(0,t.jsxs)(n.table,{children:[(0,t.jsx)(n.thead,{children:(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.th,{children:"Property"}),(0,t.jsx)(n.th,{children:"Description"}),(0,t.jsx)(n.th,{children:"Required"})]})}),(0,t.jsxs)(n.tbody,{children:[(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:(0,t.jsx)(n.code,{children:"type"})}),(0,t.jsxs)(n.td,{children:["Must be ",(0,t.jsx)(n.code,{children:'"expression"'})]}),(0,t.jsx)(n.td,{children:"Yes"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:(0,t.jsx)(n.code,{children:"name"})}),(0,t.jsx)(n.td,{children:"Output name of the post-aggregation"}),(0,t.jsx)(n.td,{children:"Yes"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:(0,t.jsx)(n.code,{children:"expression"})}),(0,t.jsxs)(n.td,{children:["Native Druid ",(0,t.jsx)(n.a,{href:"/docs/33.0.0/querying/math-expr",children:"expression"})," to compute, may refer to any dimension or aggregator output names"]}),(0,t.jsx)(n.td,{children:"Yes"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:(0,t.jsx)(n.code,{children:"ordering"})}),(0,t.jsxs)(n.td,{children:["If no ordering (or ",(0,t.jsx)(n.code,{children:"null"}),') is specified, the "natural" ordering is used. ',(0,t.jsx)(n.code,{children:"numericFirst"})," ordering always returns finite values first, followed by ",(0,t.jsx)(n.code,{children:"NaN"}),", and infinite values last. If the expression produces array or complex types, specify ",(0,t.jsx)(n.code,{children:"ordering"})," as null and use ",(0,t.jsx)(n.code,{children:"outputType"})," instead to use the correct type native ordering."]}),(0,t.jsx)(n.td,{children:"No"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:(0,t.jsx)(n.code,{children:"outputType"})}),(0,t.jsxs)(n.td,{children:["Output type is optional, and can be any native Druid type: ",(0,t.jsx)(n.code,{children:"LONG"}),", ",(0,t.jsx)(n.code,{children:"FLOAT"}),", ",(0,t.jsx)(n.code,{children:"DOUBLE"}),", ",(0,t.jsx)(n.code,{children:"STRING"}),", ",(0,t.jsx)(n.code,{children:"ARRAY"})," types (e.g. ",(0,t.jsx)(n.code,{children:"ARRAY<LONG>"}),"), or ",(0,t.jsx)(n.code,{children:"COMPLEX"})," types (e.g. ",(0,t.jsx)(n.code,{children:"COMPLEX<json>"}),"). If not specified, the output type will be inferred from the ",(0,t.jsx)(n.code,{children:"expression"}),". If specified and ",(0,t.jsx)(n.code,{children:"ordering"})," is null, the type native ordering will be used for sorting values. If the expression produces array or complex types, this value must be non-null to ensure the correct ordering is used. If ",(0,t.jsx)(n.code,{children:"outputType"})," does not match the actual output type of the ",(0,t.jsx)(n.code,{children:"expression"}),", the value will be attempted to coerced to the specified type, possibly failing if coercion is not possible."]}),(0,t.jsx)(n.td,{children:"No"})]})]})]}),"\n",(0,t.jsx)(n.p,{children:"Example:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-json",children:'{\n "type": "expression",\n "name": "someExpression",\n "expression": "someAgg + someOtherAgg",\n "ordering": null,\n "outputType": "LONG" \n}\n'})}),"\n",(0,t.jsx)(n.h3,{id:"greatest--least-post-aggregators",children:"Greatest / Least post-aggregators"}),"\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.code,{children:"doubleGreatest"})," and ",(0,t.jsx)(n.code,{children:"longGreatest"})," computes the maximum of all fields and Double.NEGATIVE_INFINITY.\n",(0,t.jsx)(n.code,{children:"doubleLeast"})," and ",(0,t.jsx)(n.code,{children:"longLeast"})," computes the minimum of all fields and Double.POSITIVE_INFINITY."]}),"\n",(0,t.jsxs)(n.table,{children:[(0,t.jsx)(n.thead,{children:(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.th,{children:"Property"}),(0,t.jsx)(n.th,{children:"Description"}),(0,t.jsx)(n.th,{children:"Required"})]})}),(0,t.jsxs)(n.tbody,{children:[(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:(0,t.jsx)(n.code,{children:"type"})}),(0,t.jsxs)(n.td,{children:["Must be ",(0,t.jsx)(n.code,{children:'"doubleGreatest"'}),", ",(0,t.jsx)(n.code,{children:'"doubleLeast"'}),", ",(0,t.jsx)(n.code,{children:'"longGreatest"'}),", or ",(0,t.jsx)(n.code,{children:'"longLeast"'}),"."]}),(0,t.jsx)(n.td,{children:"Yes"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:(0,t.jsx)(n.code,{children:"name"})}),(0,t.jsx)(n.td,{children:"Output name of the post-aggregation"}),(0,t.jsx)(n.td,{children:"Yes"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:(0,t.jsx)(n.code,{children:"fields"})}),(0,t.jsx)(n.td,{children:"List of post-aggregator specs which define inputs to the greatest or least function"}),(0,t.jsx)(n.td,{children:"Yes"})]})]})]}),"\n",(0,t.jsxs)(n.p,{children:["The difference between the ",(0,t.jsx)(n.code,{children:"doubleMax"})," aggregator and the ",(0,t.jsx)(n.code,{children:"doubleGreatest"})," post-aggregator is that ",(0,t.jsx)(n.code,{children:"doubleMax"})," returns the highest value of\nall rows for one specific column while ",(0,t.jsx)(n.code,{children:"doubleGreatest"})," returns the highest value of multiple columns in one row. These are similar to the\nSQL ",(0,t.jsx)(n.code,{children:"MAX"})," and ",(0,t.jsx)(n.code,{children:"GREATEST"})," functions."]}),"\n",(0,t.jsx)(n.p,{children:"Example:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-json",children:'{\n "type" : "doubleGreatest",\n "name" : "theGreatest",\n "fields": [\n { "type": "fieldAccess", "fieldName": "someAgg" },\n { "type": "fieldAccess", "fieldName": "someOtherAgg" }\n ]\n}\n'})}),"\n",(0,t.jsx)(n.h3,{id:"javascript-post-aggregator",children:"JavaScript post-aggregator"}),"\n",(0,t.jsx)(n.p,{children:"Applies the provided JavaScript function to the given fields. Fields are passed as arguments to the JavaScript function in the given order."}),"\n",(0,t.jsxs)(n.table,{children:[(0,t.jsx)(n.thead,{children:(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.th,{children:"Property"}),(0,t.jsx)(n.th,{children:"Description"}),(0,t.jsx)(n.th,{children:"Required"})]})}),(0,t.jsxs)(n.tbody,{children:[(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:(0,t.jsx)(n.code,{children:"type"})}),(0,t.jsxs)(n.td,{children:["Must be ",(0,t.jsx)(n.code,{children:'"javascript"'})]}),(0,t.jsx)(n.td,{children:"Yes"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:(0,t.jsx)(n.code,{children:"name"})}),(0,t.jsx)(n.td,{children:"Output name of the post-aggregation"}),(0,t.jsx)(n.td,{children:"Yes"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:(0,t.jsx)(n.code,{children:"fieldNames"})}),(0,t.jsx)(n.td,{children:"List of input dimension or aggregator output names"}),(0,t.jsx)(n.td,{children:"Yes"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:(0,t.jsx)(n.code,{children:"function"})}),(0,t.jsxs)(n.td,{children:["String javascript function which accepts ",(0,t.jsx)(n.code,{children:"fieldNames"})," as arguments"]}),(0,t.jsx)(n.td,{children:"Yes"})]})]})]}),"\n",(0,t.jsx)(n.p,{children:"Example:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-json",children:'{\n "type": "javascript",\n "name": "someJavascript",\n "fieldNames" : ["someAgg", "someOtherAgg"],\n "function": "function(someAgg, someOtherAgg) { return 100 * Math.abs(someAgg) / someOtherAgg;"\n}\n'})}),"\n",(0,t.jsx)(n.admonition,{type:"info",children:(0,t.jsxs)(n.p,{children:["JavaScript-based functionality is disabled by default. Please refer to the Druid ",(0,t.jsx)(n.a,{href:"/docs/33.0.0/development/javascript",children:"JavaScript programming guide"})," for guidelines about using Druid's JavaScript functionality, including instructions on how to enable it."]})}),"\n",(0,t.jsx)(n.h3,{id:"hyperunique-cardinality-post-aggregator",children:"HyperUnique Cardinality post-aggregator"}),"\n",(0,t.jsx)(n.p,{children:"The hyperUniqueCardinality post aggregator is used to wrap a hyperUnique object such that it can be used in post aggregations."}),"\n",(0,t.jsxs)(n.table,{children:[(0,t.jsx)(n.thead,{children:(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.th,{children:"Property"}),(0,t.jsx)(n.th,{children:"Description"}),(0,t.jsx)(n.th,{children:"Required"})]})}),(0,t.jsxs)(n.tbody,{children:[(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:(0,t.jsx)(n.code,{children:"type"})}),(0,t.jsxs)(n.td,{children:["Must be ",(0,t.jsx)(n.code,{children:'"hyperUniqueCardinality"'})]}),(0,t.jsx)(n.td,{children:"Yes"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:(0,t.jsx)(n.code,{children:"name"})}),(0,t.jsx)(n.td,{children:"Output name of the post-aggregation"}),(0,t.jsx)(n.td,{children:"Yes"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:(0,t.jsx)(n.code,{children:"fieldName"})}),(0,t.jsxs)(n.td,{children:["The output name of a ",(0,t.jsxs)(n.a,{href:"/docs/33.0.0/querying/aggregations#cardinality-hyperunique",children:[(0,t.jsx)(n.code,{children:"hyperUnique"})," aggregator"]})]}),(0,t.jsx)(n.td,{children:"Yes"})]})]})]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-json",children:'{\n "type" : "hyperUniqueCardinality",\n "name": "someCardinality",\n "fieldName" : "someHyperunique"\n}\n'})}),"\n",(0,t.jsx)(n.p,{children:"It can be used in a sample calculation as so:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-json",children:'{\n ...\n "aggregations" : [{\n {"type" : "count", "name" : "rows"},\n {"type" : "hyperUnique", "name" : "unique_users", "fieldName" : "uniques"}\n }],\n "postAggregations" : [{\n "type" : "arithmetic",\n "name" : "average_users_per_row",\n "fn" : "/",\n "fields" : [\n { "type" : "hyperUniqueCardinality", "fieldName" : "unique_users" },\n { "type" : "fieldAccess", "name" : "rows", "fieldName" : "rows" }\n ]\n }]\n ...\n'})}),"\n",(0,t.jsx)(n.p,{children:'This post-aggregator will inherit the rounding behavior of the aggregator it references. Note that this inheritance\nis only effective if you directly reference an aggregator. Going through another post-aggregator, for example, will\ncause the user-specified rounding behavior to get lost and default to "no rounding".'}),"\n",(0,t.jsx)(n.h2,{id:"example-usage",children:"Example Usage"}),"\n",(0,t.jsx)(n.p,{children:'In this example, let\u2019s calculate a simple percentage using post aggregators. Let\u2019s imagine our data set has a metric called "total".'}),"\n",(0,t.jsx)(n.p,{children:"The format of the query JSON is as follows:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-json",children:'{\n ...\n "aggregations" : [\n { "type" : "count", "name" : "rows" },\n { "type" : "doubleSum", "name" : "tot", "fieldName" : "total" }\n ],\n "postAggregations" : [{\n "type" : "arithmetic",\n "name" : "average",\n "fn" : "/",\n "fields" : [\n { "type" : "fieldAccess", "name" : "tot", "fieldName" : "tot" },\n { "type" : "fieldAccess", "name" : "rows", "fieldName" : "rows" }\n ]\n }]\n ...\n}\n'})}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-json",children:'{\n ...\n "aggregations" : [\n { "type" : "doubleSum", "name" : "tot", "fieldName" : "total" },\n { "type" : "doubleSum", "name" : "part", "fieldName" : "part" }\n ],\n "postAggregations" : [{\n "type" : "arithmetic",\n "name" : "part_percentage",\n "fn" : "*",\n "fields" : [\n { "type" : "arithmetic",\n "name" : "ratio",\n "fn" : "/",\n "fields" : [\n { "type" : "fieldAccess", "name" : "part", "fieldName" : "part" },\n { "type" : "fieldAccess", "name" : "tot", "fieldName" : "tot" }\n ]\n },\n { "type" : "constant", "name": "const", "value" : 100 }\n ]\n }]\n ...\n}\n'})}),"\n",(0,t.jsx)(n.p,{children:"The same could be computed using an expression post-aggregator:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-json",children:'{\n ...\n "aggregations" : [\n { "type" : "doubleSum", "name" : "tot", "fieldName" : "total" },\n { "type" : "doubleSum", "name" : "part", "fieldName" : "part" }\n ],\n "postAggregations" : [{\n "type" : "expression",\n "name" : "part_percentage",\n "expression" : "100 * (part / tot)"\n }]\n ...\n}\n'})})]})}function h(e={}){const{wrapper:n}={...(0,i.R)(),...e.components};return n?(0,t.jsx)(n,{...e,children:(0,t.jsx)(l,{...e})}):l(e)}}}]); |