ClickHouse中是否有简便方法检查Map包含全部指定键值对?
检查ClickHouse Map类型字段是否包含全部指定键值对
先创建测试表并插入数据:
create table map_test (my_map Map(String, String)) engine = Memory; insert into map_test values ({'k1': 'v1', 'k2': 'v2'}), ({'k1': 'v1', 'k2': 'v2', 'k3': 'v3'}), ({'k1': 'v1', 'k4': 'v4'}); select * from map_test;
执行结果:
┌─my_map──────────────────────────┐ │ {'k1':'v1','k2':'v2'} │ │ {'k1':'v1','k2':'v2','k3':'v3'} │ │ {'k1':'v1','k4':'v4'} │ └─────────────────────────────────┘ 3 rows in set. Elapsed: 0.001 sec.
如果直接用WHERE子句逐个检查键值对,当需要验证的条目较多时,SQL会变得非常冗长:
-- 获取my_map包含全部所需条目的行 select * from map_test where my_map['k1'] = 'v1' and my_map['k2'] = 'v2';
执行结果:
┌─my_map──────────────────────────┐ │ {'k1':'v1','k2':'v2'} │ │ {'k1':'v1','k2':'v2','k3':'v3'} │ └─────────────────────────────────┘ 2 rows in set. Elapsed: 0.001 sec.
ClickHouse没有内置的mapContainsAll函数,但可以通过以下几种方式实现需求:
方法1:利用mapIntersect函数
通过比较原map与目标map的交集是否等于目标map,来判断原map是否包含所有指定键值对:
select * from map_test where mapIntersect(my_map, {'k1': 'v1', 'k2': 'v2'}) = {'k1': 'v1', 'k2': 'v2'};
方法2:使用arrayAll遍历检查
将目标键值对转为元组数组,通过arrayAll逐个验证每个键值对是否存在于原map中:
select * from map_test where arrayAll( pair -> my_map[pair.1] = pair.2, [('k1', 'v1'), ('k2', 'v2')] );
方法3:创建自定义函数
如果需要重复使用该逻辑,可以创建自定义函数,实现类似mapContainsAll的效果:
CREATE FUNCTION mapContainsAll AS (map, target) -> mapIntersect(map, target) = target;
之后就可以像你期望的那样调用:
select * from map_test where mapContainsAll(my_map, {'k1': 'v1', 'k2': 'v2'});
内容的提问来源于stack exchange,提问作者jptx
相关产品推荐
相关产品推荐

