从 SQL 到 SPL:在不确定数量的列间去重
某库表有多个字段,每个字段存储一个邮件地址,有可能为空,有可能重复。
Mail_1 |
Mail_2 |
Mail_3 |
Mail_4 |
Mail_5 |
a.gmail.com |
a.aol.com |
a1.gmail.com |
a.gmail.com |
a1.gmail.com |
b.gmail.com |
b.aol.com |
b1.gmail.com |
b.yahoo.com |
现在要将多个字段合并为一个字段,去除空值和重复值,用逗号合并起来。
a.aol.com,a.gmail.com,a1.gmail.com |
b.aol.com,b.gmail.com,b.yahoo.com,b1.gmail.com |
支持 array 等数组函数的数据库 / 计算平台,比如 azure-databricks,SQL 这样写:
SELECT concat_ws(',', array_distinct(array(Mail_1, Mail_2, Mail_3, Mail_4, Mail_5)), NULL) AS Mail
FROM my_data
SQL Server 等数据库没有 array 函数,一般要用 cross apply 等语句间接实现:
SELECT
STRING_AGG(DistinctEmails.Mail, ',') AS Mail
FROM my_data
CROSS APPLY (
SELECT DISTINCT Mail
FROM (VALUES (Mail_1), (Mail_2), (Mail_3), (Mail_4), (Mail_5)) AS EmailList(Mail)
WHERE Mail IS NOT NULL
) AS DistinctEmails
GROUP BY my_data.Mail_1, my_data.Mail_2, my_data.Mail_3, my_data.Mail_4, my_data.Mail_5
SQL必须写出列名,灵活性较差。要想在不确定数量的列间去重,就要用存储过程动态生成列名再执行 SQL,结构将变得复杂。SPL 不必写出列名,且不同的数据源下代码相同:https://try.esproc.com/splx?36f
A |
|
1 |
$select * from my_data.txt |
2 |
=A1.new(~.array().id@0().concat@c():Mail) |
A1:加载数据。
A2:取当前记录,转为集合,取唯一值并去掉 null,用逗号合并。~ 表示当前记录,函数 id 用于去重,@0 表示去掉 null。