判断两字符串列子集关系:当前SPLIT+ARRAY_INTERSECT方法是否高效?
判断name列是否为full name列的子集(非相等)的SQL优化方案
我有一张包含name和full name列的表,需要判断name是否是full name的子集且两列内容不相等。示例数据如下:
| name | full name | is_subset |
|---|---|---|
| john smith | john smith | false |
| john smith | john h. smith | true |
| john smith | alice jones | false |
我已经实现了一种基于SPLIT和ARRAY_INTERSECT的方法,但想知道有没有更简洁或高效的写法。当前使用的SQL语句如下:
SELECT name, "full name", CARDINALITY( ARRAY_INTERSECT( SPLIT(name, ' '), SPLIT("full name", ' ') ) ) = CARDINALITY(SPLIT(name, ' ')) AND CARDINALITY(SPLIT("full name", ' ')) > CARDINALITY(SPLIT(name, ' ')) AS is_subset from t
更简洁的实现:利用ARRAY_CONTAINS_ALL函数
如果你的SQL引擎(比如Spark SQL、Databricks SQL、BigQuery等)支持ARRAY_CONTAINS_ALL,可以直接用这个函数简化逻辑,同时避免重复计算:
SELECT name, "full name", ARRAY_CONTAINS_ALL(SPLIT("full name", ' '), SPLIT(name, ' ')) AND name != "full name" AS is_subset FROM t
ARRAY_CONTAINS_ALL(full_name_arr, name_arr)会直接判断name拆分后的所有元素是否都存在于full name的拆分结果中,再加上name != "full name"确保两列内容不重复,完全符合需求。
提升效率:避免重复调用SPLIT
原语句中多次调用SPLIT会增加计算开销,尤其在数据量较大时。可以用CTE(公共表表达式)提前拆分字符串为数组,后续逻辑直接复用:
WITH split_names AS ( SELECT name, "full name", SPLIT(name, ' ') AS name_arr, SPLIT("full name", ' ') AS full_name_arr FROM t ) SELECT name, "full name", CARDINALITY(ARRAY_INTERSECT(name_arr, full_name_arr)) = CARDINALITY(name_arr) AND CARDINALITY(full_name_arr) > CARDINALITY(name_arr) AS is_subset FROM split_names
这种写法每个字符串只拆分一次,减少了重复计算,性能更优。
内容的提问来源于stack exchange,提问作者Josh Friedlander
相关产品推荐
相关产品推荐

