clickhouse的嵌套数据结构Tuple、Array与Nested类型介绍和使用示例

文章目录

    • Tuple类型
    • Array类型
    • Nested类型
    • 使用示例
      • 单独使用Tuple
      • 数组嵌套 Array(Tuple)
      • Nested类型
    • 生产使用:分组查询

Tuple类型

  • TupleClickHouse数据库中的一种数据类型,它允许在一个字段中存储由不同数据类型组成的元组(tuple)。
  • 元组可以包含任意数量的值,并且每个值可以是不同的数据类型,如intfloatstringdate等。
  • 例如,以下是一个clickhouse Tuple类型的例子:
    (1, 'John', 12.5, Date('2021-01-01'))

该元组包含四个值,分别是整数1,字符串’John’,浮点数12.5和日期型数据’2021-01-01’。这些值可以通过索引或字段名来访问。

  • Tuple类型可以用于存储数据结构复杂的数据,如JSONXML数据。
  • 此外,clickhouseTuple类型还可以用于支持复杂的查询和分析操作,例如在SELECT语句中使用子查询或嵌套查询,或在JOIN运算中使用多个字段来匹配复杂的条件等。

Array类型

  • Array类型表示一个包含多个相同类型元素的数组,可以通过索引访问其中的元素
  • Array类型就不详细讲了,之前写过一篇文章,有兴趣的可以点击看下
  • 当需要处理数组结构时,可以使用Array类型,而当需要处理更复杂的数据结构时,可以使用Nested类型
  • 通常,Nested类型比Array类型更加灵活,但是在性能方面可能会稍微慢一些。

Nested类型

  • ClickHouse中的Nested类型指的是复杂数据类型,它允许将多个数据类型组合成一种数据类型
  • Nested类型支持结构化数组、嵌套映射(Map)和嵌套集合(Set),可以方便地处理非标量类型的数据
  • Nested类型可以用于存储和查询具有嵌套结构的数据,例如JSONXML格式的数据。它能够支持高效的查询和聚合操作,如对嵌套数组进行平均、求和、最大、最小等操作,对于分析大量结构化数据非常有效。
  • 在使用Nested类型时,需要注意其与普通数据类型的不同之处,在查询语句中需要使用嵌套函数或语法。同时需要进行适当的数据类型转换和格式化操作,以确保数据的准确性和一致性。

使用示例

单独使用Tuple

  • 具体SQL如下,包括建表、插入数据、查询
  • 需要注意的点:
    • 字段为Tuple类型时,里面要直接是数据类型,即tuple_col Tuple(String, UInt8)
    • 插入时,只能是单个Tuple数据,不能为复数个,即(1, ('Alice', 20))
-- 建表
drop table if exists my_table_tuple;
CREATE TABLE my_table_tuple (
    id Int32,
    tuple_col Tuple(String, UInt8)
) ENGINE = MergeTree ORDER BY id;

-- 插入数据
INSERT INTO my_table_tuple VALUES
(1, ('Alice',  20)),(2, ('Bob',  35)),(3, ('Charlie',  40)),(4, ('David',  45));

-- 查询数据
SELECT * FROM my_table_tuple;
SELECT id, tuple_col.1 as name, tuple_col.2 as age  FROM my_table_tuple;
-- 注意,Tuple无法使用ARRAY JOIN,会执行报错
SELECT * FROM my_table_tuple ARRAY JOIN tuple_col;
  • 下面2个截图,为上面2个可以执行成功的SQL的查询结果
    在这里插入图片描述在这里插入图片描述

数组嵌套 Array(Tuple)

  • 数组类型,数组内为Tuple
  • 具体SQL如下,包括建表、插入数据、查询
  • 需要注意的点:
    • 此时的Tuple允许定义字段名称,即Tuple( name String, age UInt8)
    • 插入时,可以是单个Tuple数据,也可以是复数个,即(1, ['Alice','Bob'], [20, 35])
    • 需要注意的是,不能像单个Tuple类型使用时写的('Bob', 35),而是每个Tuple嵌套类型里的字段,都是一个数组,要作为数组插入
    • 插入时,行和行之间的属性的个数可以不一致 ,但是当前行的Nested类型中的字段对应的数组内的数量要一致
-- 新建表
DROP table if exists  my_table_array_tuple;
CREATE TABLE my_table_array_tuple (
    id Int32,
    array_tuple Array(
        Tuple( name String, age UInt8)
    )
) ENGINE = MergeTree ORDER BY id;

-- 插入数据
INSERT INTO my_table_array_tuple VALUES
(1, ['Alice','Bob'], [20, 35]),
(2, ['Charlie', 'David', 'Tom'], [40, 45, 34]);

-- 这个插入数据的SQL执行失败,无法类似这样插入
INSERT INTO my_table_array_tuple VALUES
(3, [('Alice',  20),('Bob',  35)]),
(4, [('Charlie',  40),('David',  45)]);

-- 查询
SELECT * FROM my_table_array_tuple;
SELECT id, array_tuple.name, array_tuple.age  FROM my_table_array_tuple;
SELECT * FROM my_table_array_tuple ARRAY JOIN array_tuple;
  • 上面三个查询SQL的查询结果,截图如下,其中前两个SQL执行结果一致
    在这里插入图片描述
  • 前两个查询结果为啥一致,为什么插入的时候是插入多个数组,看下create table执行后的表ddl就很明确了
-- `default`.my_table_array_tuple definition

CREATE TABLE default.my_table_array_tuple
(

    `id` Int32,

    `array_tuple.name` Array(String),

    `array_tuple.age` Array(UInt8)
)
ENGINE = MergeTree
ORDER BY id
SETTINGS index_granularity = 8192;
  • 第三条SQL是使用了ARRAY JOIN,分行展开们我们需要的样子
    在这里插入图片描述

Nested类型

  • 类似Tuple,但是不一样,Tuple一次只能插入一个元祖,但Nested类型既可以插入一个Nested类型数据,也可以插入多个,用起来感觉类似Array(Tuple)
  • 具体SQL如下,包括建表、插入数据、查询
  • 需要注意的点:
    • Array(Tuple)一样,此时的Nested也允许定义字段名称,即Nested( name String, age UInt8)
    • 插入数据时,也需要遵循“嵌套类型里的每一个字段对应一个数组”
    • 插入数据时,也需要遵循“单条记录内,嵌套类型每一个字段对应的值数量相同”,不同记录数量没有要求
-- 创建表
drop table if exists movies;
CREATE TABLE movies (
  title String,
  actors Nested(
    name String,
    age UInt8
  )
) ENGINE = MergeTree()
ORDER BY title;
-- 插入数据
INSERT INTO movies VALUES('Interstellar', ['Matthew McConaughey', 'Anne Hathaway'], [50, 38]);
INSERT INTO movies VALUES('The Dark Knight', ['Christian Bale', 'Heath Ledger', 'Aaron Eckhart'], [47, 28, 52]);
-- 查询
SELECT * FROM movies;
SELECT * FROM movies ARRAY JOIN actors;
-- 查询并求平均年龄
SELECT
	title,
	avg(actor.age) AS avg_age
FROM
	movies 
	ARRAY JOIN actors AS actor
GROUP BY
	title
ORDER BY
	title;
  • 第一条SQL的执行结果如下:
    在这里插入图片描述
  • 这里看下使用Nested类型创建之后表的DDL,可以发现与Tuple没啥区别
-- `default`.movies definition

CREATE TABLE default.movies
(

    `title` String,

    `actors.name` Array(String),

    `actors.age` Array(UInt8)
)
ENGINE = MergeTree
ORDER BY title
SETTINGS index_granularity = 8192;
  • 第二条SQL也是使用了ARRAY JOIN,执行结果如下:
    在这里插入图片描述
  • 第三条SQL,是查询评价年龄,是对嵌套类型里的一个字段进行运算。除了求平均,其他的函数运算也可以,聚合分组也可以
    -

生产使用:分组查询

  • 我们的安全指标表,需要存储道路级别安全指标和进口级别安全指标,建表语句(部分)如下:
-- radar.index_cycle_security definition

DROP table if exists radar.index_cycle_security;
CREATE TABLE radar.index_cycle_security
(

    `time_stamp` DateTime COMMENT '时间',

    `intersection_number` Int32 COMMENT '交叉口编号',

    `safety_factor` Float64 COMMENT '安全系数(根据下面4个安全评价参数加权计算,只计算整个路口的)',

    `phase_clearance_rate` Float64 COMMENT '相位清空率(路口)',

    `pedestrian_time_guarantee_rate` Float64 COMMENT '行人过街时间保障率(路口)',

    `pedestrian_illegal_rate` Float64 COMMENT '行人闯红灯违法率(路口)',

    `traffic_conflict` Int16 COMMENT '交通冲突次数(车道/方向)',
    
    `approach_index` Array(
    	Tuple(
    		`approach` String,
		
		    `pedestrian_time_guarantee_rate` Float64,
		
		    `pedestrian_illegal_rate` Float64 
        )
    )
)
ENGINE = MergeTree
PARTITION BY toYYYYMM(time_stamp)
PRIMARY KEY time_stamp
ORDER BY (time_stamp, intersection_number)
SETTINGS index_granularity = 8192,
 old_parts_lifetime = 300,
 max_suspicious_broken_parts = 1000;
-- 显示表结构
desc radar.index_cycle_security;
  • 现在我的业务查询需求,需要根据进口按列返回,SQL如下:
SELECT
	time_stamp ,
	approach_index.approach as approach, 
	approach_index.pedestrian_time_guarantee_rate as pedestrian_time_guarantee_rate,
	approach_index.pedestrian_illegal_rate as pedestrian_illegal_rate
FROM
	index_cycle_security ARRAY JOIN approach_index
where time_stamp = '2023-05-09 14:05:52'
order by time_stamp
  • 查询时,使用ARRAY JOIN将嵌套结构分成一个个列,查询结果如下:
    在这里插入图片描述
  • 我也可以按照时间粒度聚合(使用toStartOfInterval),之后求平均值,SQL如下:
SELECT
	toStartOfInterval(time_stamp , INTERVAL 1 HOUR) as time_stamp2 ,
	approach_index.approach as approach, 
	round(avg(approach_index.pedestrian_time_guarantee_rate), 2) as pedestrianTimeGuaranteeRate,
	round(avg(approach_index.pedestrian_illegal_rate), 2) as pedestrianIllegalRate
FROM
	index_cycle_security ARRAY JOIN approach_index
where time_stamp > '2023-05-09 14:05:52'
GROUP BY time_stamp2, approach
order by time_stamp2 
limit 0,20
  • 查询结果如下(由于都是测试数据,结果一样了,结构是可以看的):
    在这里插入图片描述
  • 看到最后的小伙伴,欢迎评论交流,给个点赞也行

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/19361.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

快速了解C语言的基本元素

C语言是一种编程语言,和其它语言一样,也定义了自己的语法和词汇。学习C语言,首先要学习C语言的词汇,再学习C语言的语法规则,然后由词汇构成语句,由语句构成源程序,源程序也称为源代码或代码&…

ChatGPT :国内免费可用 ChatGPT +Midjourney绘图

前言 ChatGPT(全名:Chat Generative Pre-trained Transformer),美国OpenAI 研发的聊天机器人程序 ,于2022年11月30日发布 。ChatGPT是人工智能技术驱动的自然语言处理工具,它能够通过理解和学习人类的语言来…

【MySQL】绪论 MySQL工作环境

文章目录 实验内容实验步骤实验内容 MySQL命令MySQL 的启动与关闭MySQL 管理备份和还原数据库navicat工具使用实验步骤 1. MySQL命令 (1)查看MySQL基本命令 (2)查看MySQL版本信息 2. MySQL的启动与关闭 (1)启动MySQL服务器 (2)测试服务器启动成功 (3)合法用

stream笔记

1、 创建流stream 1.1、 Stream 的操作三个步骤 1.2、 stream中间操作 1.2.1 、 limit、skip、distinct 1.2.2、 map and flatMap 1.2.3、 sort 自然排序和定制排序 1.3、 add and andAll difference: 1.4、 终止操作 1.4.1、 allmatch、anyMatch、noneMatch、max、min…

前端开发中,定位bug的几种常用方法

目录 第一章 前言 第二章 解决bug的方法 2.1 百度 2.2 有道翻译 2.3 debugger 2.4 console.log 日志打印 2.5 请求体是否携带参数 2.6 注释页面渲染代码 2.7 其他 第三章 尾声 备注:该文章只是本人在工作/学习中常用的几种方法,如果有不对大家…

朋友去华为面试,轻松拿到30K的Offer,羡慕了......

最近有朋友去华为面试,面试前后进行了20天左右,包含4轮电话面试、1轮笔试、1轮主管视频面试、1轮hr视频面试。 据他所说,80%的人都会栽在第一轮面试,要不是他面试前做足准备,估计都坚持不完后面几轮面试。 其实&…

第四十六章 Unity 布局(上)

学习了UI元素的使用,并不能构建出一个完整的UI界面,我们需要使用一些方法将这些UI元素按照“设计稿”的效果,将其摆放到对应的位置上。如何摆放这些UI元素,就是我们需要讲的“布局”,当然这需要借助一些布局组件来完成…

毕业论文相关

毕业论文参考文献和Word保存 一、Word中出现[7-9]多个文献的引用 在正文中选中参考文献角标,右击选择“切换域代码”,参考文献角标[7][8][9]变为{ REF _Ref98345319 \r \h * MERGEFORMAT }{ REF _Ref98345321 \r \h * MERGEFORMAT }{ REF _Ref99390603…

第5章 负载均衡

第5章 负载均衡 5.1 proxy_pass详解 在nginx中配置proxy_pass代理转发时,如果在proxy_pass后面的url加/,表示绝对根路径;如果没有/,表示相对路径,把匹配的路径部分也给代理走。 假设下面四种情况分别用 http://192.…

Java并发编程实践学习笔记(三)——共享对象之发布和异常

目录 1 公共静态变量逸出 2 非私有方法逸出私有变量 3 this引用逸出 4 构造函数中的可覆盖方法调用逸出 发布(publishing)一个对象的意思是:使对象能够在当前作用域之外的代码中使用。例如,将一个指向该对象的引用保存到其他代…

InnoDB线程模型

新版本结构演变 MySQL 5.7 版本 将 Undo日志表空间从共享表空间 ibdata 文件中分离出来,可以在安装 MySQL 时由用户自行指定文件大小和数量增加了 temporary 临时表空间,里面存储着临时表或临时查询结果集的数据Buffer Pool 大小可以动态修改&#xff0…

你不知道的自动化?使用自动化测试在项目中创造高业务价值...

目录:导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结(尾部小惊喜) 前言 脱离数据支撑谈价…

GRPC - JAVA笔记

GRPC - JAVA笔记 gRPC简介 由google开源的一个高性能的RPc框架,由google内部的Stubby框架演化而来。2015年正式开源。云原生时代的RPC标准,由Go语言开发 gRPC的核心设计思路 网络通信 ------> gRPC 自己封装了网络通信的部分,提供了多种…

VS2022编译libiconv-1.17

需求概述 获得最新版本的windows下可用的libiconv静态库。 解决方案 概述 使用VS2022编译libiconv-1.17。需要对源码手动进行配置。 本文所述的方法同样适用于动态库,并且理论上适用于VS2010~2022所有版本。 如果你不在乎libiconv的版本,可以参考 …

Redis缓存

就先不连接数据库了 我们测试缓存 实体类: Data AllArgsConstructor NoArgsConstructor public class User implements Serializable {private int id;private String name;private String sex;private String addr; } service: Service public…

小家电LED显示驱动多功能语音芯片IC方案 WT2003H4 B002

随着时代的进步,智能家电的普及已经成为了一个趋势。而在智能家电中,LED显示屏也成为了不可或缺的一部分。因此,在小家电的设计中,LED显示驱动芯片的应用也越来越广泛。比如:电饭煲、电磁炉、数字时钟、咖啡机、电磁炉…

java版spring cloud 企业电子招投标采购系统源码之首页设计

随着公司的快速发展,企业人员和经营规模不断壮大,公司对内部招采管理的提升提出了更高的要求。在企业里建立一个公平、公开、公正的采购环境,最大限度控制采购成本至关重要。符合国家电子招投标法律法规及相关规范,以及审计监督要…

“正大杯”第十三届市场调查与分析大赛[省一]经验总结+复盘

目录 1 前期组队 2 队员组成 队长-成员1 应用统计学专业 成员2 化学实验专业 成员3-本人 物联网工程专业 成员4 金融ACCA专业 成员5 应用物理学 总结 3 比赛进度 3月中旬 部分图表的制作 问卷设计与制作 稍微改动主题 问卷相关总结 前期调查部分论文框架 3月…

怎么把webp文件转换为jpg?这几种方法值得学习!

怎么把webp文件转换为jpg,我想这样的问题对于那些和图片打交道不多的人来说确实有些困难吧。在我们要处理这个问题之前,我们先来了解一下图片格式webp吧。要是知道Youtube、Gmail、Google Play 中都可以看到 WebP 的身影,而 Chrome 网上商店甚…

高阶python | 堆栈列表:RPN应用(模拟逆波兰式功能实现)

python版本:3.10 在列表中,append和pop方法有一个特殊的用途。可以在列表上使用这两个方法让列表变成一个堆栈使用。 这就是一个栈,它是先进后出,类似单门轿厢电梯一样的设计,出入口共用 堆栈最有用的应用之一就是做逆…