官方说明:
根据column和hash函数的值,将table分区为一组groups个表。hash函数应用于column行的值,以获取该行的哈希值。哈希值模数 groups 确定要将该行放入所返回的哪个表中。
table:要分区的表。
column:要执行哈希运算以确定该行位于返回的哪个表中的列。
groups:要对输入表进行分区的表数。
hash:应用以获取哈希值的函数。
Table.Partition( table as table, column as text, groups as number, hash as function) as list
解读:
顾名思义,这是一个分表函数。为什么要分表?分表后每个表是独立的List元素,可以批量转化再供下一步调用!
看最简单的案例,类似分组,如下面按a列分组= Table.Partition(源,"a",2,each _)
第二参数为分表依据的字段,第三参数控制输出表的个数,最有意思的是第四参数,也是最灵活难理解的地方。当你认为所有的a列一样的就会自动分组到一起时,打脸就来了:你把a列的两个1都改成0试一下!
根据语法我觉得分表的法则是三四参数在搞鬼,比如现在分2组,那么= Table.Partition(源,"a",2,each _)
想当然的得给我2和0分开啊!然而并没有,他们仍然是好基友分在了一组里面,为什么会这样?
其实关键点就在于对第二参数的参考对象与分组数进行了Mod运算!他就等价于= Table.Partition(源,"a",2,each Number.Mod(_,2))
,这样就可以解释打脸的分组了。。。
你再测试下将a列对象改为2,0,4,6进行分表= Table.Partition(源,"a",3,each _)
看到没,0和6分一组了!
如果仅仅是这样分表就没啥意思了,我会想到能否自定义分组?回答是:必须可以啊!
各位看官也许注意到了等价公式中的Mod,那么我们可以直接调整Mod的第二参数就能打乱原有的分组布局!
= Table.Partition(源,"a",4,each Number.Mod(_,5))
也就是产生每个对象与5进行Mod运算后的值分组情况!
甚至有些同学会想到能改Mod第二参数,那么Mod第一参数呢?各位看官说干就干吧。。。
很多时候我们的分组依据是文本,你无法直接进行数值运算,这个时候要分组我们就要找文本的规律转换成数值参与分组!
也许你会用得上List.PositionOf
函数获取文本定位的数字、或许你会配合Number.IntegerDivide
等函数强制转换分组!
有的人已经注意到一点就是第三参数的特殊情况,当你的数据是动态无法确定一个分组定值时你需要思考合理转化过来!
然而我就是不按套路出牌呢?明明是3组或许我就要填分5组?那么组数不等于哈希值分组数的情况下怎么分表?
测试发现会产生多余空表,在测试过程中我发现分表的顺序是按哈希值的大小排列的:= Table.Partition(源,"a",5,each _)
哈希值从小到大(0..x)匹配的哈希值分表放到对应位置,另一种情况才能让你完全理解这个哈希值排布情况!
当我们第三参数强制分组表的个数小于实际第四参数值的类数时,= Table.Partition(源,"a",2,each Number.Mod(_,4))
直接写第四参数直接写each _转换过程可以理解为分两部走,第一步对源参考对象列未做转换处理,再与组数2进行Mod运算。那么这里就是,第一步对源对象{2,5,2,9,7}转换为{2,1,2,1,3},再拿{2,1,2,1,3}与组数2进行Mod运算产生{0,1,0,1,1,1},最后按照从小到大分布哈希值结果即为上图情况!注意第四参数我说的转换,这里刚好是用了Mod,也可以是其他函数的嵌套转换或是直接数学运算表达式!
当第三参数强制了分组数后,必然会与第四参数实际哈希值类有冲突,前面提到第三参数大于第四参数哈希值类的情况,各位自己测试哈希值类多的情况的排列规律,至此方能完全理解他的分组排布情况。
SQL里面提供分区函数(会指定分区依据,和本文的function类似)的分区表(这里的分区表是物理上文件存储的分区表,逻辑上没有差别,一般使用做常用非常用数据的分离,而进行查询优化)的形式,当分区即groups的数值大于hashd的数值是会有个标记next used的分区,反之是会被报错的,不知道这样的理解是不是更恰当。
散列hash,循环hash,好吧,如果是mod方式,那救接近于循环哈希了,首尾相连,物理节点插入到最近的哈希节点。
我也只是最近才开始学,大神勿喷。
文章倒数第3行的第4组说明数据中,多写了一个“1”。