gpt4 book ai didi

elasticsearch - 类似 GROUP BY AND HAVING 的 SQL

转载 作者:行者123 更新时间:2023-11-29 02:44:28 25 4
gpt4 key购买 nike

我想获得满足特定条件的组数。在 SQL 术语中,我想在 Elasticsearch 中执行以下操作。

SELECT COUNT(*) FROM
(
SELECT
senderResellerId,
SUM(requestAmountValue) AS t_amount
FROM
transactions
GROUP BY
senderResellerId
HAVING
t_amount > 10000 ) AS dum;

到目前为止,我可以通过术语聚合按 senderResellerId 进行分组。但是当我应用过滤器时,它并没有按预期工作。

弹性请求

{
"aggregations": {
"reseller_sale_sum": {
"aggs": {
"sales": {
"aggregations": {
"reseller_sale": {
"sum": {
"field": "requestAmountValue"
}
}
},
"filter": {
"range": {
"reseller_sale": {
"gte": 10000
}
}
}
}
},
"terms": {
"field": "senderResellerId",
"order": {
"sales>reseller_sale": "desc"
},
"size": 5
}
}
},
"ext": {},
"query": { "match_all": {} },
"size": 0
}

实际响应

{
"took" : 21,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"failed" : 0
},
"hits" : {
"total" : 150824,
"max_score" : 0.0,
"hits" : [ ]
},
"aggregations" : {
"reseller_sale_sum" : {
"doc_count_error_upper_bound" : -1,
"sum_other_doc_count" : 149609,
"buckets" : [
{
"key" : "RES0000000004",
"doc_count" : 8,
"sales" : {
"doc_count" : 0,
"reseller_sale" : {
"value" : 0.0
}
}
},
{
"key" : "RES0000000005",
"doc_count" : 39,
"sales" : {
"doc_count" : 0,
"reseller_sale" : {
"value" : 0.0
}
}
},
{
"key" : "RES0000000006",
"doc_count" : 57,
"sales" : {
"doc_count" : 0,
"reseller_sale" : {
"value" : 0.0
}
}
},
{
"key" : "RES0000000007",
"doc_count" : 134,
"sales" : {
"doc_count" : 0,
"reseller_sale" : {
"value" : 0.0
}
}
}
}
}
]
}
}
}

从上面的响应中可以看出,它正在返回经销商,但 reseller_sale 聚合结果为零。

更多细节是here .

最佳答案

实现HAVING -喜欢的行为

您可以使用 pipeline aggregations 之一, 即 bucket selector aggregation .查询看起来像这样:

POST my_index/tdrs/_search
{
"aggregations": {
"reseller_sale_sum": {
"aggregations": {
"sales": {
"sum": {
"field": "requestAmountValue"
}
},
"max_sales": {
"bucket_selector": {
"buckets_path": {
"var1": "sales"
},
"script": "params.var1 > 10000"
}
}
},
"terms": {
"field": "senderResellerId",
"order": {
"sales": "desc"
},
"size": 5
}
}
},
"size": 0
}

将以下文档放入索引后:

  "hits": [
{
"_index": "my_index",
"_type": "tdrs",
"_id": "AV9Yh5F-dSw48Z0DWDys",
"_score": 1,
"_source": {
"requestAmountValue": 7000,
"senderResellerId": "ID_1"
}
},
{
"_index": "my_index",
"_type": "tdrs",
"_id": "AV9Yh684dSw48Z0DWDyt",
"_score": 1,
"_source": {
"requestAmountValue": 5000,
"senderResellerId": "ID_1"
}
},
{
"_index": "my_index",
"_type": "tdrs",
"_id": "AV9Yh8TBdSw48Z0DWDyu",
"_score": 1,
"_source": {
"requestAmountValue": 1000,
"senderResellerId": "ID_2"
}
}
]

查询结果为:

"aggregations": {
"reseller_sale_sum": {
"doc_count_error_upper_bound": 0,
"sum_other_doc_count": 0,
"buckets": [
{
"key": "ID_1",
"doc_count": 2,
"sales": {
"value": 12000
}
}
]
}
}

即仅那些累计销售额为 >10000senderResellerId

数桶

要实现 SELECT COUNT(*) FROM (... HAVING) 的等价物,可以使用 bucket script aggregation 的组合与 sum bucket aggregation .虽然似乎没有直接的方法来计算 bucket_selector 实际选择了多少个桶,但我们可以定义一个 bucket_script 来生成 01 取决于条件,以及产生其 sumsum_bucket:

POST my_index/tdrs/_search
{
"aggregations": {
"reseller_sale_sum": {
"aggregations": {
"sales": {
"sum": {
"field": "requestAmountValue"
}
},
"max_sales": {
"bucket_script": {
"buckets_path": {
"var1": "sales"
},
"script": "if (params.var1 > 10000) { 1 } else { 0 }"
}
}
},
"terms": {
"field": "senderResellerId",
"order": {
"sales": "desc"
}
}
},
"max_sales_stats": {
"sum_bucket": {
"buckets_path": "reseller_sale_sum>max_sales"
}
}
},
"size": 0
}

输出将是:

   "aggregations": {
"reseller_sale_sum": {
"doc_count_error_upper_bound": 0,
"sum_other_doc_count": 0,
"buckets": [
...
]
},
"max_sales_stats": {
"value": 1
}
}

所需的存储桶计数位于 max_sales_stats.value 中。

重要注意事项

我必须指出两点:

  1. 该功能是实验性的(从 ES 5.6 开始它仍然是实验性的,尽管它是在 2.0.0-beta1 中添加的。)
  2. 管道聚合应用于先前聚合的结果:

Pipeline aggregations work on the outputs produced from other aggregations rather thanfrom document sets, adding information to the output tree.

这意味着 bucket_selector 聚合将在 senderResellerId 上的 terms 聚合结果之后应用。例如,如果 senderResellerId 多于 terms 聚合定义的 size,您将不会获得所有 ID在具有 sum(sales) > 10000 的集合中,但仅出现在 terms 聚合输出中的那些。考虑使用排序和/或设置足够的 size 参数。

这也适用于第二种情况,COUNT() (... HAVING),它只会计算聚合输出中实际存在的那些桶。

如果这个查询太重或桶的数量太多,考虑denormalizing您的数据或将此总和直接存储在文档中,因此您可以使用普通的 range查询以实现您的目标。

关于elasticsearch - 类似 GROUP BY AND HAVING 的 SQL,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46908360/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com