跳转到主要内容
嵌套数据结构就像单元格中的一张表。嵌套数据结构的参数——列名和类型——其指定方式与 CREATE TABLE 查询中的写法相同。表中的每一行都可以对应嵌套数据结构中的任意多行。
避免在列名中使用点号flatten_nested = 1 (默认值) 时,包含点号的列名、具有相同点号前缀的列,以及 Array 类型的列,都可能被解释为扁平化 Nested 结构的一部分。这可能导致在插入时出现意外的数组长度校验,以及重命名限制。如无必要,请避免在列名中使用点号。 除非你确实需要 Nested 语义,否则请在列名中使用下划线 (_) 或其他分隔符来代替点号。
示例:
上述 CREATE TABLE DDL 语句声明了 Goals 嵌套数据结构,其中包含有关转化或已实现目标的数据。 visits 表中的每一行都对应零次或多次转化。 flatten_nested 设置为 0 时 (默认值为 flatten_nested=1) ,支持任意级别的嵌套。 在大多数情况下,处理嵌套数据结构时,其列使用以点分隔的列名来指定。 这些列构成一个由对应类型组成的数组。 同一个嵌套数据结构中的所有列数组长度都相同。 例如:
可以把嵌套数据结构简单理解为一组长度相等的多个列数组。

在 WHERE 中过滤 Nested 列

由于 Nested 结构中的每一列都存储为 Array,因此在 WHERE 子句中引用它时,拿到的是每一行的整个数组,而不是单个元素。你不能将嵌套列直接与标量值比较,因此必须改用数组函数 例如,这个查询不会悄悄地返回 0 行——它会引发异常,因为 Goals.ID 的类型是 Array(UInt32),而 equals(Array(UInt32), UInt32) 不是有效的比较:
使用 has 检查数组是否包含特定值:
如果条件较为复杂,可使用 arrayExists
你可以使用 length 根据数组长度进行过滤,或使用 notEmpty 排除空数组:
若要针对嵌套结构中的单个元素进行过滤,而不是针对整行过滤,请先使用 ARRAY JOIN 将数组展开。 在 ARRAY JOIN 之后,每个元素都会成为单独的一行,因此 WHERE 子句会作用于标量值。 更多信息,请参见 ARRAY JOIN 子句。示例:
你不能对整个嵌套数据结构执行 SELECT。只能显式列出其中的各个列。

插入数据

对于 INSERT 查询,应分别传入嵌套数据结构中各组成列的数组 (就像它们是彼此独立的列数组一样) 。插入时,系统会检查它们的长度是否一致。 每个嵌套子列都会在列列表中以点表示法列出 (Goals.IDGoals.Serial 等) ,相应的值则为数组:
单行中的所有嵌套子列数组长度必须相同。长度不一致会报错:
对于 DESCRIBE 查询,嵌套数据结构中的各列也会以相同方式分别列出。

ALTER 的限制

对嵌套数据结构执行 ALTER 查询时有以下限制: 添加子列 可正常使用。你可以向现有的 Nested 结构添加新的子列:
删除子列可用于单个子列:
修改类型 对子列同样适用,并会触发一次变更 (数据重写) :
重命名 存在一些限制。你可以在同一个嵌套结构内重命名子列:
但是,你不能
  • 重命名整个嵌套结构 (例如,将 Goals 改为 Conversions) 。
  • 将子列移动到其他嵌套结构中 (例如,将 Goals.ID 移动到 OtherNested.ID) 。
  • 将子列移出嵌套结构,或移入嵌套结构 (例如,将 Goals.ID 改为 GoalID,反之亦然) 。
最后修改于 2026年6月25日