SQL中如何查询结构体(struct)数组内满足条件的字段值
问题原因
你之前写的SQL无法满足需求的核心原因是:直接访问数组类型字段的子属性(比如table.data.values.primaryKey),会返回数组中所有元素对应子属性组成的新数组,只能做全数组层面的包含判断,无法绑定同一个结构体元素内的primaryKey和date1做关联校验。
这类嵌套结构体数组的字段级关联校验,需要用数组高阶遍历函数实现逐元素判断。
正确SQL实现
以下写法适配Spark SQL(从你给出的Schema打印格式判断你用的是Spark引擎),完全匹配两个校验规则:
SELECT * FROM table WHERE -- 规则2:存在primaryKey为"10"的元素,且该元素的date1晚于当前时间 EXISTS( data, elem -> elem.values.primaryKey = '10' AND elem.date1 > current_timestamp() ) -- 规则1:所有primaryKey为"12"的元素,对应date1都不晚于当前时间 AND NOT EXISTS( data, elem -> elem.values.primaryKey = '12' AND elem.date1 > current_timestamp() );
逻辑说明
EXISTS(数组, 元素 -> 判断条件):逐元素遍历数组,只要有1个元素满足判断条件就返回true,刚好匹配规则2「必须存在符合要求的primaryKey=10元素」的要求,替换掉你原来用的array_contains,同时绑定了同元素的date1判断。- 规则1用
NOT EXISTS的写法兼容性最好,逻辑是「不存在任何一个primaryKey=12且date1超标的元素」,等价于所有primaryKey=12的元素都符合date1要求,比FORALL函数支持的Spark版本范围更广。 - 这里用
current_timestamp()而非current_date()做比较,是因为你的date1字段是timestamp类型,同类型比较可以避免隐式转换带来的时区、精度偏差问题。 - 如果你的引擎支持
FORALL高阶函数,规则1也可以写成如下等价形式,可读性更强:
AND FORALL( data, elem -> IF(elem.values.primaryKey = '12', elem.date1 <= current_timestamp(), true) )
内容的提问来源于stack exchange,提问作者user3281103
相关产品推荐
相关产品推荐

