近期遇到一个困惑的问题,自定义函数中,如果出现查询语句,则传递的参数,不能传递字段名,只能传递常量或者表达式,文档中也没有找到对应的解决办法。
需求其实比较简单,查询的时候,要做一个"少数服从多数"的决定,在一行记录中,存在多个字段值是String类型,使用哪个字段值,取决于字段内容出现的频率次数最高的字符串,注意,这里是一行记录,可以理解成,一个数组字段类型,常规想法就是 select group by ,但是,就出现了开头说的问题,不能传递字段名称作为参数。
sql
CREATE function my_count as (str1 ,str2 ,str3 )-> (
SELECT max(element)
from
(
SELECT
arrayJoin(array) AS element,
count(*) AS count
FROM (
SELECT [str1,str2,str] AS array
)
where LENGTH(element)>0
GROUP BY element
ORDER BY count DESC
limit 1
) t
)
上述代码,传递常量是没有问题的,但是:
select my_count(field1,field2,field3) as a from my_table
就会报错,提示不支持字段作为参数
后来,只能从文档的方法来入手,找内置的arry相关函数
CREATE FUNCTION my_test as (arr) ->arrayReverseSort((m,n)->n, arrayMap(x->(x,countEqual(arr,x)),arrayDistinct(arr)))
这里就很好解决了需求,不过,性能可能会低一点,起码先凑合着用着。
arrayDistinct 表示数组的元素取唯一,去重。
countEqual 表示计算元素在数组中出现的次数
arrayMap 把统计元素个数映射成 (key,count)的格式,其中count就是计数
arrayReverseSort 就是倒序,根据第2个参数(count)进行排序
在使用中 SELECT uniqTotal(['a','b','b','a','a'])[1].1 AS ele
其中[1]表示取数组的第一个元素,.1表示取key值,就是需求目标
完美解决,如果有更好的办法,麻烦留言告知,谢谢!