ARRAY JOIN 子句最基本的用法。
它之所以得名,是因为可以将其视为对数组或嵌套数据结构执行 JOIN。其用途与 arrayJoin 函数类似,但子句的功能更为广泛。
语法:
ARRAY JOIN 类型:
ARRAY JOIN- 在默认情况下,空数组不会包含在JOIN结果中。LEFT ARRAY JOIN-JOIN结果中会包含带空数组的行。对于空数组,其值会被设置为该数组元素类型的默认值 (通常为 0、空字符串或 NULL) 。
ARRAY JOIN 基本示例
ARRAY JOIN 和 LEFT ARRAY JOIN
ARRAY JOIN 和 LEFT ARRAY JOIN 子句的用法。我们先创建一个包含 Array 类型列的表,并向其中插入值:
ARRAY JOIN 子句:
LEFT ARRAY JOIN 子句:
ARRAY JOIN 与 arrayEnumerate 函数
ARRAY JOIN 搭配使用。它可以在应用 ARRAY JOIN 后,对每个数组只统计一次。示例:
ARRAY JOIN 后得到的字符串数量) ,而 Hits 表示页面浏览量 (即 ARRAY JOIN 之前的字符串数量) 。在这种情况下,你也可以用更简单的方式得到相同结果:
ARRAY JOIN 和 arrayEnumerateUniq
ARRAY JOIN 并对数组元素进行聚合时非常有用。
在此示例中,会计算每个目标 ID 的转化次数 (Goals 嵌套数据结构中的每个元素都是一个已达成的目标,我们称其为一次转化) 以及 session 数量。如果不使用 ARRAY JOIN,我们会将 session 数量统计为 sum(Sign)。但在这个特定场景中,行被嵌套的 Goals 结构展开了,因此为了确保之后每个 session 只被计数一次,我们对 arrayEnumerateUniq(Goals.ID) 函数的返回值应用了条件。
使用别名
ARRAY JOIN 子句中的数组指定别名。在这种情况下,可以通过该别名访问数组元素,而数组本身仍使用原始名称访问。示例:
ARRAY JOIN。例如:
ARRAY JOIN 子句中用逗号分隔。在这种情况下,会同时对这些数组执行 JOIN (即直接和,而不是笛卡儿积) 。请注意,默认情况下,所有数组的大小都必须相同。示例:
SETTINGS enable_unaligned_array_join = 1 对多个大小不同的数组进行 join。示例:
ARRAY JOIN 与嵌套数据结构配合使用
ARRAY JOIN 也可用于嵌套数据结构:
ARRAY JOIN 中指定嵌套数据结构的名称时,其含义与对该结构所包含的所有数组元素执行 ARRAY JOIN 相同。示例如下:
JOIN 结果或源数组。示例:
实现细节
ARRAY JOIN 时,查询的执行顺序会被优化。虽然在查询中,ARRAY JOIN 必须始终写在 WHERE/PREWHERE 子句之前,但从技术上讲,它们实际上可以按任意顺序执行,除非过滤会用到 ARRAY JOIN 的结果。执行顺序由查询优化器控制。
与短路函数求值不兼容
if、multiIf、and 和 or 等特定函数中复杂表达式的执行。它可以防止这些函数在执行过程中出现潜在异常,例如除以零。
arrayJoin 始终会被执行,因此不支持短路函数求值。这是因为它是一个特殊函数,在查询分析和执行期间会独立于其他所有函数单独处理,并且需要额外的逻辑,而这套逻辑无法与短路函数执行兼容。原因在于,结果中的行数取决于 arrayJoin 的结果,而为 arrayJoin 实现惰性执行过于复杂且代价过高。