ClickHouse 通过 ​*ARRAY JOIN* 结合 ​Map 类型的内置函数取数值

news/2025/3/14 13:12:26/

在 ClickHouse 中,可以通过 ​ARRAY JOIN 结合 ​Map 类型的内置函数,将 Map 字段的键值对展开为多行数据。以下是具体操作方法和示例:


一、使用 mapKeys 和 mapValues 展开 Map

1. 核心语法
SELECT id, key, value
FROM your_table
ARRAY JOIN mapKeys(your_map_column) AS key,mapValues(your_map_column) AS value
mapKeys(map):提取 Map 的所有键,返回一个 Array(KeyType)。​mapValues(map):提取 Map 的所有值,返回一个 Array(ValueType)。​ARRAY JOIN:将两个数组按顺序展开为多行,键和值一一对应。
2. 示例

假设表结构如下:

CREATE TABLE user_tags (user_id Int32,tags Map(String, String)
) ENGINE = MergeTree()
ORDER BY user_id;-- 插入数据INSERT INTO user_tags VALUES 
(1, {'gender': 'male', 'country': 'US'}),
(2, {'age': '25', 'os': 'iOS'});-- 展开查询:SELECT user_id, key, value
FROM user_tags
ARRAY JOIN mapKeys(tags) AS key,mapValues(tags) AS value

输出:

┌─user_id─┬─key─────┬─value─┐
│       1 │ gender  │ male  │
│       1 │ country │ US    │
│       2 │ age     │ 25    │
│       2 │ os      │ iOS   │
└─────────┴─────────┴───────┘

二、直接使用 .Keys 和 .Values 语法(ClickHouse 22.6+ 支持)

从 ClickHouse 22.6 开始,可以直接通过 Map.Keys 和 Map.Values 访问键值数组:

SELECT user_id, key, value
FROM user_tags
ARRAY JOIN tags.Keys AS key,tags.Values AS value

三、使用 mapEntries 展开为键值对元组

1. 核心语法
SELECT id, entry.1 AS key,  -- 元组第一个元素为键entry.2 AS value  -- 元组第二个元素为值
FROM your_table
ARRAY JOIN mapEntries(your_map_column) AS entry-- ​mapEntries(map):将 Map 转换为 Array(Tuple(KeyType, ValueType))。
2. 示例
SELECT user_id, entry.1 AS key,entry.2 AS value
FROM user_tags
ARRAY JOIN mapEntries(tags) AS entry

四、过滤特定键值对

在展开后,可通过 WHERE 子句筛选特定键或值:

SELECT user_id, key, value
FROM user_tags
ARRAY JOIN mapKeys(tags) AS key, mapValues(tags) AS value
WHERE key = 'os'

输出:

┌─user_id─┬─key─┬─value─┐
│       2 │ os  │ iOS   │
└─────────┴─────┴───────┘

五、性能优化建议

  1. 避免展开大 Map
    Map 展开后行数会爆炸式增长(如 10,000 个键值对 → 10,000 行),建议在 WHERE 条件中提前过滤。

  2. 预聚合高频键值
    将常用键单独存为列,避免每次查询展开:

ALTER TABLE user_tags
ADD COLUMN os String MATERIALIZED tags['os'];

六、总结

通过 ARRAY JOIN 结合以下方法展开 Map:

方法适用场景
mapKeys + mapValues兼容所有 ClickHouse 版本
.Keys + .ValuesClickHouse 22.6+ 版本更简洁写法
mapEntries直接展开为元组,适合键值对联合操作

http://www.ppmy.cn/news/1579045.html

相关文章

【21】单片机编程核心技巧:if语句逻辑与真假判断

【21】单片机编程核心技巧:if语句逻辑与真假判断 七律 条件分野 if语句判真假,括号条件定乾坤。 非零为真零为假,大括号内藏玄门。 省略虽简风险在,代码规范护本根。 单片逻辑由心控,条件分支自成文。 注释&#xf…

【Node.js入门笔记5---fs文件信息与元数据】

Node.js入门笔记5 Node.js---fs 文件信息与元数据一、文件信息与元数据1.fs.stat() / fs.statSync():获取文件或目录的详细信息(大小、类型、修改时间等)。异步同步 2.fs.access():检查文件是否存在或是否有访问权限。3.fs.symlin…

2024 年第四届高校大数据挑战赛-赛题 A:岩石的自动鉴定

问题1:沉积岩薄片识别模型设计问题分析核心任务:基于“南京大学沉积岩教学薄片照片数据集”,构建多类别分类模型,区分火山碎屑岩、砂岩、泥页岩等9类沉积岩。特征提取需求: 颜色特征:矿物成分差异导致偏光下…

【一个月备战蓝桥算法】递归与递推

字典序 在刷题和计算机科学领域,字典序(Lexicographical order)也称为词典序、字典顺序、字母序,是一种对序列元素进行排序的方式,它模仿了字典中单词的排序规则。下面从不同的数据类型来详细解释字典序: …

无服务器数据库

无服务器数据库(Serverless Database)是一种新兴的数据库架构模式,旨在简化数据库管理、提升资源利用率并降低运营成本。通过自动化资源管理和弹性扩展,无服务器数据库使开发者能够更加专注于应用程序的开发而无需关心底层基础设施…

nginx实现tomcat反向代理

nginx的配置 定义一个组实现负载均衡 记录真实的客户端IP 记录下客户端的IP 第二个也同上修改

process monitor获取栈信息

下面是process monitor获取到的栈信息 首先用命令行起windbg -z 加载对应的dll 可以看到模块的起始位置,加载对应的pdb后,用 ln 起始位置 偏移 就可以看到对应的函数以及行数

数据结构与算法:归并排序

目录 归并排序的基本思想 归并排序的特性总结 代码 归并排序的非递归版 归并排序的基本思想 归并排序是建立在归并操作上的一种有效的排序算法。改算法是采用分治法的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列…