分类 我爱编程 下的文章

MySQL的语句执行顺序

  1. FORM: 对FROM的左边的表和右边的表计算笛卡尔积。产生虚表VT1

  2. ON: 对虚表VT1进行ON筛选,只有那些符合<join-condition>的行才会被记录在虚表VT2中。

  3. JOIN: 如果指定了OUTER JOIN(比如left join、 right join),那么保留表中未匹配的行就会作为外部行添加到虚拟表VT2中,产生虚拟表VT3, rug from子句中包含两个以上的表的话,那么就会对上一个join连接产生的结果VT3和下一个表重复执行步骤1~3这三个步骤,一直到处理完所有的表为止。

  4. WHERE: 对虚拟表VT3进行WHERE条件过滤。只有符合<where-condition>的记录才会被插入到虚拟表VT4中。

  5. GROUP BY: 根据group by子句中的列,对VT4中的记录进行分组操作,产生VT5.

  6. CUBE | ROLLUP: 对表VT5进行cube或者rollup操作,产生表VT6.

  7. HAVING: 对虚拟表VT6应用having过滤,只有符合<having-condition>的记录才会被 插入到虚拟表VT7中。

  8. SELECT: 执行select操作,选择指定的列,插入到虚拟表VT8中。

  9. DISTINCT: 对VT8中的记录进行去重。产生虚拟表VT9.

  10. ORDER BY: 将虚拟表VT9中的记录按照<order_by_list>进行排序操作,产生虚拟表VT10.

  11. LIMIT:取出指定行的记录,产生虚拟表VT11, 并将结果返回。

PHP设计模式之观察者模式FUN版

使用协程模式:


<?php
/*********观察者模式FUNC版*******/
use functionSwoole\Coroutine\run;
use functionSwoole\Coroutine\go;
useSwoole\Coroutine\System;

$user  = [
   'name'=>'',
   'email'=>'',
   'mobile'=>'',
   'updates'=> [],
   'OnUpdate'=>function($update)use(&$user) {
       array_push($user['updates'],$update);
   },
   'Update'=>function()use(&$user) {
       foreach($user['updates']as$update){
           go(function()use($update,&$user){
               $update($user);
               System::sleep(3);
           });
       };
//            sleep(5);
   },
   'Register'=>function($name,$email,$mobile)use(&$user) {
       $user['name'] =$name;
       $user['email'] =$email;
       $user['mobile'] =$mobile;
       $user['Update']();
   },
];
$user["OnUpdate"](function($subject){
   echo"send email to ".$subject['email'] .PHP_EOL;
});
$user["OnUpdate"](function($subject){
   echo"send sms to ".$subject['mobile'] .PHP_EOL;
});
$user['Register']("紫羽·大薯","345374113@qq.com","1888888888");
echo"我先提前完成输出";
\Swoole\Event::wait();



elasticsearch聚合--桶(Buckets)和指标(Metrics)的概念

主要内容包括:

  1. 聚合的两个核心概念:桶(bucket)和指标(metric)

  2. 桶和指标的深入理解

  3. 示例说明

 ---------------------------------------------------------------------

1、聚合的两个核心概念                                                           

  在Elasticsearch的聚合中需要掌握两个核心的概念:桶(bucket)、指标(metric)

    桶(bucket): 满足特定条件的文档的集合

    指标(metric): 对桶内的文档进行聚合分析的操作

  (ps:每个聚合都是一个或者多个桶和零个或者多个指标的组合。)

翻译成粗略的SQL语句来解释的话:

SELECT COUNT(color)  ---> 相当于指标

FROM table

GROUP BY color  --->2  相当于桶

桶在概念上类似于SQL的分组(GROUP BY),而指标则类似于COUNT()、SUM()、MAX()等统计方法。

---------------------------------------------------------------------

2、桶和指标的深入理解                                                          

(1)桶  

  a、简单来说桶就是满足特定条件的文档的集合。

  b、当聚合开始被执行,每个文档里面的值通过计算来决定符合哪个桶的条件,如果匹配到,文档将放入相应的桶并接着开始聚合操作。

  c、桶也可以被嵌套在其他桶里面。

(2)指标

  a、桶能让我们划分文档到有意义的集合,但是最终我们需要的是对这些桶内的文档进行一些指标的计算。分桶是一种达到目的地的手段:它提供了一种给文档分组的方法来让我们可以计算感兴趣的指标。

  b、大多数指标是简单的数学运算(如:最小值、平均值、最大值、汇总),这些是通过文档的值来计算的。

(3)桶和指标的组合

  聚合是由桶和指标组成的。聚合可能只有一个桶,可能只有一个指标,或者可能两个都有。也有可能一些桶嵌套在其他桶里面。

---------------------------------------------------------------------

3、举例说明                                                                        

比如有如下的数据:

  city  name

  北京  小李

  北京  小王

  上海  小张

  上海    小丽

  上海  小陈

基于city来划分buckets的话,可以划分出两个bucket:一个是北京bucket、一个是上海bucket

  北京bucket:包含了2个人,小李、小王

  上海bucket:包含了3个人,小张、小丽、小陈

按照某个字段进行bucket划分,那个字段的值相同的那些数据,就会被划分到一个bucket中。当我们有了一堆bucket之后,就可以对每个bucket中的数据聚合分析了,比如说计算一个bucket内所有数据的数量 ,或者计算一个bucket内所有数据的平均值、最大值、最小值。

metric : 就是对一个bucket执行的某种聚合分析的操作,比如说求平均值、最大值、最小值 。

上面利用elasticsearch的分组,可以转化成对应的sql语句如下:

  select count(*) from access_log group by user_id

其中:bucket 相当于 group by user_id -->那些user_id相同的数据,就会被划分到一个bucket中

   metric 相当于 count(*) -->对每个user_id bucket中所有的数据计算一个数量  



Elasticsearch笔记:聚合查询之多字段查询分组

2.1 先分组, 再聚合统计

(1) 先按tags分组, 再计算每个tag下图书的平均价格, 请求语法:

GET book_shop / it_book / _search 
{
	"size": 0,
	"aggs": {
		"group_by_tags": {
			"terms": {
				"field": "tags.keyword"
			},
			"aggs": {
				"avg_price": {
					"avg": {
						"field": "price"
					}
				}
			}
		}
	}
}


(2) 响应结果:

{
	"hits": {
		"total": 3,
		"max_score": 0.0,
		"hits": []
	},
	"aggregations": {
		"group_by_tags": {
			"doc_count_error_upper_bound": 0,
			"sum_other_doc_count": 0,
			"buckets": [{
					"key": "Java",
					"doc_count": 3,
					"avg_price": {
						"value": 102.33333333333333
					}
				},
				{
					"key": "编程语言",
					"doc_count": 2,
					"avg_price": {
						"value": 114.0
					}
				},
				......
			]
		}
	}

2.2 先分组, 再统计, 最后排序

(1) 计算每个tag下图书的平均价格, 再按平均价格降序排序, 查询语法:

GET book_shop / it_book / _search 
{
	"size": 0,
	"aggs": {
		"all_tags": {
			"terms": {
				"field": "tags.keyword",
				"order": {
					"avg_price": "desc"
				} // 根据下述统计的结果排序
			},
			"aggs": {
				"avg_price": {
					"avg": {
						"field": "price"
					}
				}
			}
		}
	}
}

(2) 响应结果:

与#2.1节内容相似, 区别在于按照价格排序显示了.

2.3 先分组, 组内再分组, 然后统计、排序

(1) 先按价格区间分组, 组内再按tags分组, 计算每个tags组的平均价格, 查询语法:

GET book_shop/it_book/_search
{
	"size": 0,
	"aggs": {
		"group_by_tags": {
			"terms": {
				"field": "tags.keyword"
			},
			"aggs": {
				"avg_price": {
					"avg": {
						"field": "price"
					}
				}
			}
		}
	}
}



(2) 响应结果:

{
	"hits": {
		"total": 3,
		"max_score": 0.0,
		"hits": []
	},
	"aggregations": {
		"group_by_price": {
			"buckets": [{
					"key": "0.0-100.0", // 区间0.0-100.0
					"from": 0.0,
					"to": 100.0,
					"doc_count": 1, // 共查找到了3条文档
					"group_by_tags": { // 对tags分组聚合
						"doc_count_error_upper_bound": 0,
						"sum_other_doc_count": 0,
						"buckets": [{
								"key": "Java",
								"doc_count": 1,
								"avg_price": {
									"value": 79.0
								}
							},
							......
						]
					}
				},
				{
					"key": "100.0-150.0",
					"from": 100.0,
					"to": 150.0,
					"doc_count": 2,
					"group_by_tags": {
						"doc_count_error_upper_bound": 0,
						"sum_other_doc_count": 0,
						"buckets": [{
								"key": "Java",
								"doc_count": 2,
								"avg_price": {
									"value": 114.0
								}
							},
							......
						}
					]
				}
			}
		]
	}
}


Elasticsearch笔记:聚合查询之分页

  • 正常情况下是不支持聚合后分页的,以下的原理是按照某个字段分组(桶),再对组(桶)进行排序或直接截断(分页)

  • 分页后是得不到分组后的组的总个数,目前采用的方法是先去查询组的总个数,然后分页,接着将两个结果合在一起使用

POST /log_*/_search
{
  "size": 0,
  "aggs": {
    "day": {
      "date_histogram": {
        "field": "@timestamp",
        "interval": "day",
        "format": "yyyy-MM-dd"
      },
    "aggs": {
      "bucket_truncate": {
        "bucket_sort": {
          "from": 0,
          "size": 20
        }
      }
    }
    }
  }
}

解释

  • 第一个size
    表示返回0条数据(hits中的数据)

  • 第一个aggs
    表示对@timestamp按照天进行分组,并将结果进行日期格式化

  • 第二个aggs
    对结果进行排序,这里没有排序,只做了截断(分页)

这样就实现了对聚合的结果进行了分页

备注

1

获取分组后,分了几组(总数),可以再次调用接口查询数据,取查询到数据的个数即可(记得去掉第二的aggs),这是目前想到最笨的办法,如果你有更好的办法可以分享一下呦!


官网:
https://www.elastic.co/guide/en/elasticsearch/reference/6.8/search-aggregations-pipeline-bucket-sort-aggregation.html