Julian Reyes
05/07/2024, 10:45 AM[
{
"ts": "2024-04-29T12:00:00.000Z",
"network": "polygon",
"total": 197944
},
{
"ts": "2024-04-29T12:00:00.000Z",
"network": "ethereum",
"total": 1994412
},
{
"ts": "2024-04-29T12:00:00.000Z",
"network": "celo",
"total": 1234
},
{
"ts": "2024-04-29T12:00:00.000Z",
"network": "All Others",
"total": 123
},
.
.
.
{
"ts": "2024-04-30T11:00:00.000Z",
"network": "polygon",
"total": 193953
},
{
"ts": "2024-04-30T11:00:00.000Z",
"network": "ethereum",
"total": 19393
},
{
"ts": "2024-04-30T11:00:00.000Z",
"network": "celo",
"total": 111
},
{
"ts": "2024-04-29T12:00:00.000Z",
"network": "All Others",
"total": 11
},
]
I am particularly interested in whether we can get the All Others by just showing the top3 or top4 and then all others get aggregated into that fieldLaksh Singla
05/07/2024, 10:48 AMJulian Reyes
05/07/2024, 10:50 AMLaksh Singla
05/07/2024, 10:52 AMJulian Reyes
05/07/2024, 10:54 AM{
"ts": "2024-04-29T12:00:00.000Z",
"network": "A",
"total": 197944
},
{
"ts": "2024-04-29T12:00:00.000Z",
"network": "B",
"total": 1994412
},
{
"ts": "2024-04-29T12:00:00.000Z",
"network": "C",
"total": 1234
},
{
"ts": "2024-04-29T12:00:00.000Z",
"network": "All Others",
"total": 123
},
but always with a determined info showing the top3 or the top4 and everything else in All Others . The idea is to render a stacked bar chart where each bar will be shown for each timestampGian Merlino
05/07/2024, 4:43 PMAll Others on the client side by subtraction
i'm sure there's a fancier way, that would actually produce a result from a single query like the one you mentioned, involving window functions. something like the following. however note that it does require window fns (currently experimental) and will also require loading up all of the distinct countryName in memory in order to compute the ranks and re-group the "All others". so it will have limitations if there's a lot of distinct countryName. (which there aren't, because there aren't that many countries, but there may be a lot of network in your example)
select
case when least(rnk, 4) < 4 then countryName else 'All others' end as Country,
sum("cnt") as "cnt"
from (
select
rank() over (order by count(*) desc) rnk,
countryName,
count(*) as "cnt"
from wikipedia
where countryName is not null
group by countryName
)
group by 1, least(rnk, 4)
order by least(rnk, 4)Julian Reyes
05/08/2024, 9:38 AMGian Merlino
05/09/2024, 5:15 AMexplain plan for on the SQL query to see what the native query would beJulian Reyes
05/09/2024, 11:36 AM{
"queryType": "groupBy",
"dataSource": {
"type": "query",
"query": {
"queryType": "windowOperator",
"dataSource": {
"type": "query",
"query": {
"queryType": "groupBy",
"dataSource": {
"type": "table",
"name": "test_dev"
},
"intervals": {
"type": "intervals",
"intervals": [
"2024-05-08T12:00:00.000Z/2024-05-09T12:00:00.001Z"
]
},
"filter": {
"type": "and",
"fields": [
{
"type": "equals",
"column": "user_id",
"matchValueType": "STRING",
"matchValue": "1234abcd"
},
{
"type": "not",
"field": {
"type": "null",
"column": "network"
}
}
]
},
"granularity": {
"type": "all"
},
"dimensions": [
{
"type": "default",
"dimension": "network",
"outputName": "d0",
"outputType": "STRING"
}
],
"aggregations": [
{
"type": "count",
"name": "a0"
}
],
"limitSpec": {
"type": "NoopLimitSpec"
},
"context": {
"enableWindowing": true,
"queryId": "f4b80893-f3ba-4a18-be45-a04ad3e3854a",
"sqlOuterLimit": 1001,
"sqlQueryId": "f4b80893-f3ba-4a18-be45-a04ad3e3854a",
"useNativeQueryExplain": true
}
}
},
"intervals": {
"type": "LegacySegmentSpec",
"intervals": [
"-146136543-09-08T08:23:32.096Z/146140482-04-24T15:36:27.903Z"
]
},
"context": {
"enableWindowing": true,
"queryId": "f4b80893-f3ba-4a18-be45-a04ad3e3854a",
"sqlOuterLimit": 1001,
"sqlQueryId": "f4b80893-f3ba-4a18-be45-a04ad3e3854a",
"useNativeQueryExplain": true
},
"outputSignature": [
{
"name": "d0",
"type": "STRING"
},
{
"name": "a0",
"type": "LONG"
},
{
"name": "w0",
"type": "LONG"
}
],
"operatorDefinition": [
{
"type": "naiveSort",
"columns": [
{
"column": "a0",
"direction": "DESC"
}
]
},
{
"type": "naivePartition",
"partitionColumns": []
},
{
"type": "window",
"processor": {
"type": "rank",
"group": [
"a0"
],
"outputColumn": "w0",
"asPercent": false
}
}
],
"leafOperators": [],
"granularity": {
"type": "all"
}
}
},
"intervals": {
"type": "intervals",
"intervals": [
"-146136543-09-08T08:23:32.096Z/146140482-04-24T15:36:27.903Z"
]
},
"virtualColumns": [
{
"type": "expression",
"name": "v0",
"expression": "case_searched((least(\"w0\",4) < 4),\"d0\",'All others')",
"outputType": "STRING"
},
{
"type": "expression",
"name": "v1",
"expression": "least(\"w0\",4)",
"outputType": "LONG"
}
],
"granularity": {
"type": "all"
},
"dimensions": [
{
"type": "default",
"dimension": "v0",
"outputName": "_d0",
"outputType": "STRING"
},
{
"type": "default",
"dimension": "v1",
"outputName": "_d1",
"outputType": "LONG"
}
],
"aggregations": [
{
"type": "longSum",
"name": "_a0",
"fieldName": "a0"
}
],
"limitSpec": {
"type": "default",
"columns": [
{
"dimension": "_d1",
"direction": "ascending",
"dimensionOrder": {
"type": "numeric"
}
}
],
"limit": 1001
},
"context": {
"enableWindowing": true,
"queryId": "f4b80893-f3ba-4a18-be45-a04ad3e3854a",
"sqlOuterLimit": 1001,
"sqlQueryId": "f4b80893-f3ba-4a18-be45-a04ad3e3854a",
"useNativeQueryExplain": true
}
}
I am not sure where this intervals comes from: -146136543-09-08T08:23:32.096Z/146140482-04-24T15:36:27.903Z. If I change them for 2024-05-08T12:00:00.000Z/2024-05-09T12:00:00.001Z then I get null pointer but I found out it is because I need to change the granularity from:
"granularity": {
"type": "all"
},
to:
"granularity": {
"type": "period",
"period": "PT1H",
"timeZone": "Etc/UTC"
},
however with above changes I get nothing.
In order to get results I need to keep granularity type all and -146136543-09-08T08:23:32.096Z/146140482-04-24T15:36:27.903Z intervals.
The SQL query:
select
case when least(rnk, 4) < 4 then network else 'All others' end as Network,
sum("cnt") as "cnt"
from (
select
rank() over (order by count(*) desc) rnk,
network,
count(*) as "cnt"
from "test_dev"
where "network" is not null and "user_id" = '1234abcd' and __time BETWEEN TIMESTAMP '2024-05-08 12:00:00' AND TIMESTAMP '2024-05-09 12:00:00'
group by network
)
group by 1, least(rnk, 4)
order by least(rnk, 4)Julian Reyes
05/09/2024, 11:50 AMselect
time_hour,
case when least(rnk, 4) < 4 then network else 'All others' end as Network,
sum("cnt") as "cnt"
from (
select
TIME_FLOOR(__time, 'PT1H') as time_hour,
rank() over (order by count(*) desc) rnk,
network,
count(*) as "cnt"
from "test_dev"
where "network" is not null and "user_id" = '1234' and __time BETWEEN TIMESTAMP '2024-05-08 12:00:00' AND TIMESTAMP '2024-05-09 12:00:00'
group by network, TIME_FLOOR(__time, 'PT1H')
)
group by time_hour, 2, least(rnk, 4)
order by least(rnk, 4)
but not giving the desired resultJulian Reyes
05/09/2024, 12:25 PMselect
time_hour,
case when rnk > 100 then network else 'All others' end as network,
sum("total") as "total"
from (
select
TIME_FLOOR(__time, 'PT1H') as time_hour,
RANK() over (order by count(*) desc) rnk,
network,
count(*) as "total"
from "test_dev"
where "network" is not null and "user_id" = '1234' and __time BETWEEN TIMESTAMP '2024-05-08 12:00:00' AND TIMESTAMP '2024-05-09 12:00:00'
group by network, TIME_FLOOR(__time, 'PT1H')
order by 1 asc
)
group by time_hour, 2
order by 1 asc, 3 asc
however, not sure how best resolve this use case.
If we always want the top 3 Networks and everything else in All Others label, then for customer 1234 that submits requests to 10 different networks, I guess we get a nice result, but for a customer abcd that submits requests to only 2 networks, then it might make not sense to display All Others in the result set right?Julian Reyes
05/09/2024, 2:57 PM1234 makes requests up to 8 different networks (we want, e.g. top2 and All Others)
• user abcd only makes requests up to 2 different networks (we do not want All Others to be rendered)Gian Merlino
05/09/2024, 9:18 PM-146136543-09-08T08:23:32.096Z/146140482-04-24T15:36:27.903Z, that's just because there is no time filter. It's how we represent a SQL query with no time filter in a native query [where time filter is required] -- min possible timestamp to max possible timestampGian Merlino
05/09/2024, 9:18 PMGian Merlino
05/09/2024, 9:19 PMcase when rnk > 100 then network else 'All others' end as network, i think you want that to be < 100 instead of > 100Julian Reyes
05/10/2024, 11:00 AMselect
time_hour,
case when least(rnk, 4) < 4 then network else 'All others' end as network,
sum("total") as "total"
from (
select
TIME_FLOOR(__time, 'PT1H') as time_hour,
rank() over (order by count(*) desc) rnk,
network,
count(*) as "total"
from "test_dev"
where "network" is not null and "user_id" = '1234' and __time BETWEEN TIMESTAMP '2024-05-08 12:00:00' AND TIMESTAMP '2024-05-09 12:00:00'
group by network, TIME_FLOOR(__time, 'PT1H')
)
group by time_hour, 2, least(rnk, 2)
order by time_hour, network asc
Above I am specifying a time filter and I am getting still in the middle of the json query
"intervals": {
"type": "LegacySegmentSpec",
"intervals": [
"-146136543-09-08T08:23:32.096Z/146140482-04-24T15:36:27.903Z"
]
},
and near the bottom
"intervals": {
"type": "intervals",
"intervals": [
"-146136543-09-08T08:23:32.096Z/146140482-04-24T15:36:27.903Z"
]
},Gian Merlino
05/10/2024, 3:35 PMGian Merlino
05/10/2024, 3:36 PMintervals for 2024-05-08 12:00:00 to 2024-05-09 12:00:00 for one of the subqueries—the one that queries test_dev directly— and the intervals on the other subqueries will still be -146136543-09-08T08:23:32.096Z/146140482-04-24T15:36:27.903Z (each subquery has its own set of intervals)Julian Reyes
05/10/2024, 3:42 PMJulian Reyes
05/10/2024, 3:43 PMGian Merlino
05/10/2024, 3:50 PM-146136543-09-08T08:23:32.096Z/146140482-04-24T15:36:27.903Z is kind of like a special interval that means "don't time filter". in our SQL planner code it's a constant Intervals.ETERNITY. if you are writing native queries directly you can use it anytime a query or subquery doesn't need to filter what's below it
in most cases a more-specific time filter is only needed on the lowest-level query that hits the table directlyJulian Reyes
05/10/2024, 4:06 PMJulian Reyes
05/10/2024, 4:07 PMJulian Reyes
05/10/2024, 4:08 PMGian Merlino
05/10/2024, 4:11 PMAll Others if the # of networks returned is less than the rank threshold you'd defined? i believe that should happen "automatically" since the case statement will never return All Others if no network has a rank greater than the number in thereGian Merlino
05/10/2024, 4:11 PMAll Others to be dynamic somehowJulian Reyes
05/10/2024, 4:12 PMJulian Reyes
05/10/2024, 4:13 PM100 , I added it for testing, but result set differs from customer to customer depending how many requests they have made to our API for specific networksJulian Reyes
05/10/2024, 4:14 PM1234 only requests 2 networks however customer abcd 8 networks, but on the other hand customer 1234 might only use 2 networks but for 1 network have a rank over 100 and the other network rank of 50, so if I use 100 then result set shows 1 network and All Others containing only 1 other networkJulian Reyes
05/10/2024, 4:15 PMGian Merlino
05/10/2024, 4:21 PM1234 has only 2 networks then one will have rank 1 and one will have rank 2Julian Reyes
05/10/2024, 9:18 PMGian Merlino
05/10/2024, 10:30 PMGian Merlino
05/10/2024, 10:31 PMGian Merlino
05/10/2024, 10:32 PMJulian Reyes
05/14/2024, 9:26 AMAll Others should be determined per time period right? but I though we were doing so with following query
select
TIME_FLOOR(__time, 'PT1H') as time_hour,
RANK() over (order by count(*) desc) as rnk,
network,
count(*) as "total"
from "monopipe_dev"
where "network" is not null and "user_id" = 'c2d6c42a8b0b4da4816cdad307a54850' and __time BETWEEN TIMESTAMP '2024-05-08 12:00:00' AND TIMESTAMP '2024-05-09 12:00:00'
group by network, TIME_FLOOR(__time, 'PT1H')
order by 1 asc
or do we somehow have to include the time period within RANK() over … ?Julian Reyes
05/14/2024, 9:38 AMselect
time_hour,
case when least(rnk, 3) < 3 then network else 'All others' end as network,
sum("total") as "total"
from (
select
TIME_FLOOR(__time, 'PT1H') as time_hour,
RANK() over (PARTITION by TIME_FLOOR(__time, 'PT1H') order by count(*) desc) as rnk,
network,
count(*) as "total"
from "test_dev"
where "network" is not null and "user_id" = 'abcd' and __time BETWEEN TIMESTAMP '2024-05-08 12:00:00' AND TIMESTAMP '2024-05-09 12:00:00'
group by network, TIME_FLOOR(__time, 'PT1H')
)
group by time_hour, 2
order by time_hour, 3 asc
give below resultset: a customer that submits requests for more than 3 different networks across time periodJulian Reyes
05/14/2024, 9:39 AMselect
time_hour,
case when least(rnk, 3) < 3 then network else 'All others' end as network,
sum("total") as "total"
from (
select
TIME_FLOOR(__time, 'PT1H') as time_hour,
RANK() over (PARTITION by TIME_FLOOR(__time, 'PT1H') order by count(*) desc) as rnk,
network,
count(*) as "total"
from "test_dev"
where "network" is not null and "user_id" = '1234' and __time BETWEEN TIMESTAMP '2024-05-08 12:00:00' AND TIMESTAMP '2024-05-09 12:00:00'
group by network, TIME_FLOOR(__time, 'PT1H')
)
group by time_hour, 2
order by time_hour, 3 asc
following resultset: a customer that only submits requests to 2 different networks across time period:Julian Reyes
05/14/2024, 10:06 AM1715169600000 instead of 2024-05-08T12:00:00.000Z format, I see I get:
"virtualColumns": [
{
"type": "expression",
"name": "v0",
"expression": "timestamp_floor(\"__time\",'PT1H',null,'UTC')",
"outputType": "LONG"
}
],
...
"dimensions": [
{
"type": "default",
"dimension": "payload_method",
"outputName": "d0",
"outputType": "STRING"
},
{
"type": "default",
"dimension": "v0",
"outputName": "d1",
"outputType": "LONG"
}
],
....
"outputSignature": [
{
"name": "d0",
"type": "STRING"
},
{
"name": "d1",
"type": "LONG"
},
{
"name": "a0",
"type": "LONG"
},
{
"name": "w0",
"type": "LONG"
}
],
....
"operatorDefinition": [
{
"type": "naiveSort",
"columns": [
{
"column": "d1",
"direction": "ASC"
},
{
"column": "a0",
"direction": "DESC"
}
]
},
{
"type": "naivePartition",
"partitionColumns": [
"d1"
]
},
...
"dimensions": [
{
"type": "default",
"dimension": "d1",
"outputName": "_d0",
"outputType": "LONG"
},
{
"type": "default",
"dimension": "v0",
"outputName": "_d1",
"outputType": "STRING"
}
],
"aggregations": [
{
"type": "longSum",
"name": "_a0",
"fieldName": "a0"
}
],
"limitSpec": {
"type": "default",
"columns": [
{
"dimension": "_d0",
"direction": "ascending",
"dimensionOrder": {
"type": "numeric"
}
},
{
"dimension": "_a0",
"direction": "ascending",
"dimensionOrder": {
"type": "numeric"
}
}
],
"limit": 1001
},
probably something I need to tweak with virtualColumns right?Gian Merlino
05/14/2024, 11:37 AMGian Merlino
05/14/2024, 11:38 AMexpression post-aggregator at the outermost query that does a timestamp_format expressionGian Merlino
05/14/2024, 11:39 AMSELECT TIME_FORMAT(time_hour) … instead of SELECT time_hour … at the first line of your queryJulian Reyes
05/14/2024, 11:48 AMJulian Reyes
05/14/2024, 11:49 AMJulian Reyes
05/14/2024, 11:50 AM"postAggregations": [
{
"type": "expression",
"name": "s0",
"expression": "timestamp_format(\"_d0\",'yyyy-MM-dd\\u0027T\\u0027HH:mm:ss.SSSZZ','UTC')",
"outputType": "STRING"
}
],Julian Reyes
05/14/2024, 11:58 AMTIME_FORMAT(time_hour, 'yyyy-MM-ddTHH:mm:ssZ', 'UTC'), ?Julian Reyes
05/14/2024, 1:59 PMTIME_FORMAT(time_hour, 'yyyy-MM-ddTHH:mm:ssZ', 'UTC'), does not work but TIME_FORMAT(time_hour, 'yyyy-MM-dd HH:mm:ss', 'UTC'), doesGian Merlino
05/14/2024, 5:05 PMyyyy-MM-ddTHH:mm:ssZ you need to escape the T and ZGian Merlino
05/14/2024, 5:06 PMTIME_FORMAT(time_hour, 'yyyy-MM-dd''T''HH:mm:ss''Z''', 'UTC')Julian Reyes
05/14/2024, 5:11 PMJulian Reyes
05/23/2024, 3:47 PM...
"dimensionExclusions": [
"__time",
"count",
"ts",
"sum_credit_units"
],
"includeAllDimensions": false,
"useSchemaDiscovery": false
},
"metricsSpec": [
{
"type": "count",
"name": "count"
},
{
"type": "longSum",
"name": "sum_credit_units",
"fieldName": "credit_units"
}
],
...
It links to how much it costed to user to submit that request to our API, now I want:
select
TIME_FORMAT(time_hour, 'yyyy-MM-dd''T''HH:mm:ss''Z''', 'UTC'),
case when least(rnk, 5) < 5 then network else 'All others' end as network,
sum("credits") as "credits"
from (
select
TIME_FLOOR(__time, 'PT1H') as time_hour,
RANK() over (PARTITION by TIME_FLOOR(__time, 'PT1H') order by count(*) desc) as rnk,
network,
"sum_credit_units" as "credits"
from "test_dev"
where "network" is not null and "user_id" = 'abcd' and __time BETWEEN TIMESTAMP '2024-05-23 15:27:00' AND TIMESTAMP '2024-05-24 15:27:00'
group by network, TIME_FLOOR(__time, 'PT1H'), sum_credit_units
)
group by time_hour, 2
order by time_hour, 3 asc
but I am not sure if it is right, since the result set I got for All Others is too high (173785) and in dev there is no much going on, not sure if the query is rightJulian Reyes
05/28/2024, 2:38 PMcount metric, but what I was really after was another metric (shared above sum_credit_units)
select
TIME_FORMAT(time_hour, 'yyyy-MM-dd''T''HH:mm:ss''Z''', 'UTC'),
case when least(rnk, 5) < 5 then "payload_method" else 'All others' end as payload_method,
sum("credits") as "credits"
from (
select
TIME_FLOOR(__time, 'PT1H') as time_hour,
RANK() over (PARTITION by TIME_FLOOR(__time, 'PT1H') order by count(*) desc) as rnk,
payload_method,
"sum_credit_units" as "credits"
from "test_dev"
where "payload_method" is not null and "user_id" = 'abcd' and __time BETWEEN TIMESTAMP '2024-05-27 09:00:00' AND TIMESTAMP '2024-05-28 09:00:00'
group by payload_method, TIME_FLOOR(__time, 'PT1H'), sum_credit_units
)
group by time_hour, 2
order by time_hour, 3 asc
above query give me this result: but I know it is wrong since for a given day and hour I have total 1506712 count (2024-05-27T090000Z). Currently credit_units is 1 for every row. Not sure if I am missing somethingJulian Reyes
05/28/2024, 2:41 PMselect
TIME_FLOOR(__time, 'PT1H') as time_hour,
RANK() over (PARTITION by TIME_FLOOR(__time, 'PT1H') order by count(*) desc) as rnk,
payload_method,
sum("sum_credit_units") as "credits"
from "test_dev"
where "payload_method" is not null and "user_id" = 'abcd' and __time BETWEEN TIMESTAMP '2024-05-27 09:00:00' AND TIMESTAMP '2024-05-28 09:00:00'
group by payload_method, TIME_FLOOR(__time, 'PT1H')
that give me below: so it is a matter of combining to get the All Others thing but cant make it workJulian Reyes
05/28/2024, 2:43 PMselect
TIME_FORMAT(time_hour, 'yyyy-MM-dd''T''HH:mm:ss''Z''', 'UTC'),
case when least(rnk, 5) < 5 then "payload_method" else 'All others' end as payload_method,
sum("credits") as "credits"
from (
select
TIME_FLOOR(__time, 'PT1H') as time_hour,
RANK() over (PARTITION by TIME_FLOOR(__time, 'PT1H') order by count(*) desc) as rnk,
payload_method,
sum("sum_credit_units") as "credits"
from "test_dev"
where "payload_method" is not null and "user_id" = 'abcd' and __time BETWEEN TIMESTAMP '2024-05-27 09:00:00' AND TIMESTAMP '2024-05-28 09:00:00'
group by payload_method, TIME_FLOOR(__time, 'PT1H')
)
group by time_hour, 2
order by time_hour, 3 ascGian Merlino
06/05/2024, 8:25 AMJulian Reyes
06/05/2024, 12:39 PMRANK() over (PARTITION by TIME_FLOOR(__time, 'PT1H') order by count(*) desc) as rnk, in the inner query, giving it for each 1h bucket in the whole 24h period, but not sure if we should have the All Others aggregated in the 24h period instead of 1h bucket windows, an not sure if possible at all