ARRAY JOIN | ClickHouse Documentation
ARRAY JOIN 子句允许在数据表的内部,与数组或嵌套类型的字段进行 JOIN 操作,从而将一行数组展开为多行。接下来让我们看看它的基础用法。
-- 首先新建一张包含 Array 数组字段的测试表
CREATE TABLE query_v1
(
title String,
value Array(UInt8)
) ENGINE = Log;
-- 接着写入测试数据
INSERT INTO query_v1 VALUES ('food', [1,2,3]), ('fruit', [3,4]), ('meat', []);
SELECT title,value FROM query_v1;
┌─title──┬─value──────┐
│ food │ [1,2,3] │
│ fruit │ [3,4] │
│ meat │ [] │
└────────┴────────────┘
在一条 SELECT 语句中,只能存在一个 ARRAY JOIN(使用子查询除外)。目前支持 INNER 和 LEFT 两种 JOIN 策略:
INNER ARRAY JOIN
ARRAY JOIN 在默认情况下使用的是 INNER JOIN 策略,例如下面的语句:
SELECT title,value FROM query_v1 ARRAY JOIN value
┌─title──┬───value──┐
│ food │ 1 │
│ food │ 2 │
│ food │ 3 │
│ fruit │ 3 │
│ fruit │ 4 │
└────────┴──────────┘
从查询结果可以发现,最终的数据基于 value 数组被展开成了多行,并且排除掉了空数组。在使用 ARRAY JOIN 时,如果为原有的数组字段添加一个别名,则能够访问展开前的数组字段,例如:
SELECT title,value,**v** FROM query_v1 **ARRAY JOIN value AS v**
┌─title──┬─value────┬─v──┐
│ food │ [1,2,3] │ 1 │
│ food │ [1,2,3] │ 2 │
│ food │ [1,2,3] │ 3 │
│ fruit │ [3,4] │ 3 │
│ fruit │ [3,4] │ 4 │
└────────┴──────────┴────┘
LEFT ARRAY JOIN
ARRAY JOIN 子句支持 LEFT 连接策略,例如执行下面的语句:
SELECT title,value,v FROM query_v1 **LEFT ARRAY JOIN value AS v**
┌─title──┬─value────┬─v──┐
│ food │ [1,2,3] │ 1 │
│ food │ [1,2,3] │ 2 │
│ food │ [1,2,3] │ 3 │
│ fruit │ [3,4] │ 3 │
│ fruit │ [3,4] │ 4 │
│ meat │ [] │ 0 │
└────────┴──────────┴────┘
在改为 LEFT 连接查询后,可以发现,在 INNER JOIN 中被排除掉的空数组出现在了返回的结果集中。
当同时对多个数组字段进行 ARRAY JOIN 操作时,查询的计算逻辑是按行合并而不是产生笛卡儿积,例如下面的语句:
-- ARRAY JOIN 多个数组时,是合并,不是笛卡儿积
SELECT
title,
value,
v,
arrayMap(x -> x * 2,value) as mapv,
v_1
FROM query_v1
LEFT ARRAY JOIN value AS v , mapv as v_1;
┌─title─┬──value──┬─v─┬─mapv────┬─v_1─┐
│ food │ [1,2,3] │ 1 │ [2,4,6] │ 2 │
│ food │ [1,2,3] │ 2 │ [2,4,6] │ 4 │
│ food │ [1,2,3] │ 3 │ [2,4,6] │ 6 │
│ fruit │ [3,4] │ 3 │ [6,8] │ 6 │
│ fruit │ [3,4] │ 4 │ [6,8] │ 8 │
│ meat │ [] │ 0 │ [] │ 0 │
└───────┴─────────┴───┴─────────┴─────┘
value 和 mapv 数组是按行合并的,并没有产生笛卡儿积。
在前面介绍数据定义时曾介绍过,嵌套数据类型的本质是数组,所以 ARRAY JOIN 也支持嵌套数据类型。接下来继续用一组示例说明。
-- ARRAY JOIN 嵌套类型
CREATE TABLE query_v2
(
title String,
nest Nested(
v1 UInt32,
v2 UInt64)
) ENGINE = Log
-- 接着写入测试数据,在写入嵌套数据类型时,记得同一行数据中各个数组的长度需要对齐,而对多行数据之间的数组长度没有限制
INSERT INTO query_v2 VALUES ('food', [1,2,3], [10,20,30]), ('fruit', [4,5], [40,50]), ('meat', [], [])
SELECT title, nest.v1, nest.v2 FROM query_v2
┌─title─┬─nest.v1─┬─nest.v2───┐
│ food │ [1,2,3] │ [10,20,30]│
│ fruit │ [4,5] │ [40,50] │
│ meat │ [] │ [] │
└───────┴─────────┴───────────┘