对于排序规则明显的数据集,使用neighbor来做分析,是一个非常强大的函数,能完成很多复杂的计算,例如高速公路分析车辆流量。
高速公路截面流量一般是通过路面上的门架采集设备采集通行卡的信息和识别牌照组成,在路面行驶的车辆,受天气、车辆密集度、电子卡片、采集设备等因素影响,也不能100%准确采集到通行数据,如果仅仅以单一采集点来分析流量,准确度必然打折扣。不过,任何方法都不能说完全准确分析出数据,肯定存在一定误差的。
以上就是应用场景说明。把采集从点改为线,相对来说,就准确很多,还能过滤掉重复的数据,思路就是以采集点为中心,向前后各取2-3个采集点的数据,形成“线”数据,并对采集点进行编号,从进入到驶出,编号为1、2、3、4、5、6、7,要分析的点是4号点,这个点的设置,需要人工配置好,或者做成临时表,注意,序号必须在表中体现出来。
把要分析的数据,根据时间段和采集点整体查询出来
select id,车牌号 as vid,通过时间 as tTime,门架编号 as gid from passTable
where 门架编号 in ('s01','s02','s03','s04','s05','s06','s07')
and 通过时间 between '2024-01-01' and '2024-01-01'
order by 车牌号,通过时间
把上述查询,放到临时表 tmpTable,一个月的记录数,大概有千万记录,服务器必须有足够的内存。接下来就要放大招
select id
,neighbor(vid,-1,NULL) as p_vid,vid,neighbor(vid,1,NULL) as n_vid
,neighbor(tTime,-1,NULL) as p_tTime,tTime,neighbor(tTime,1,NULL) as n_tTime
,gid
from tmpTable
order by vid,tTime
问题一:看起来没毛病,实际上,中间总有些数据不是意料中的理想数据,也就是说neighbor不灵光了!
问题二:用with viewTable as ( ) 或者 create temporary tmpTable as () ,select 中出现了window相关函数,就是 over(partition by ....)这样的,哪怕把neighbor放到临时表内,也会改变数据结果,感觉,neighbor优先级是最低的
把上述查询,再放到另外一个查询临时表 tempTable2
select groupArray(gid) over(partition by vid order by vid,tTime) as gidArray,* from tempTable2
你会发现 原来设定的p_vid 就不一样了
仔细研究了文档,确实是和window函数有关,但是,没说怎么解决!
在研究好好几天发现了几个有效的方法:
1、排序 order by vid,tTime 和 order (by vid,tTime)还是有差别的,后者使用起来更加顺手。
2、大量数据使用排序后的neighbor函数,要达到预期效果,设置max_block_size,值为Int64最大值,不同版本值不一样,一般设置Int32最大值也都足够了。
3、window函数会导致neighbor不可预期,起码我没研究清楚,谨慎使用!研究清楚后再来汇报
经过一系列改造,基本按预计出结果,但是数据上,出现干扰数据,也需要想办法处理掉,经过10多天的研究,终于包流量计算和有入无出的分析都弄出来了,数据校验基本是通过了,期间踩了不少坑,也学了不少。