对来自不同 table 中的列的值使用 ILIKE ANY
use ILIKE ANY on values from a column in a different table
有一个电子邮件域列表并且想要标记 'free' 如果该域类似于免费域,
这适用于我这样的硬编码列表:
CASE WHEN lower(email_domain) ilike any ('%%gmail%%','%%yahoo%%', '%%hotmail%%') THEN 'free' else 'business' end
但我真正想做的是从不同 table 的列中获取免费域列表,看起来像这样:
| SUBSTRING_VALUE |
|:------------------|
| "gmail" |
| "hotmail" |
| "yahoo" |
我试过使用带有 listagg 或 arrayagg 的子查询,但它不起作用,
有什么办法吗?
使用JOIN
:
SELECT DISTINCT t.*,
CASE WHEN f.domain IS NOT NULL THEN 'free' ELSE 'business' END AS email_type
FROM test t
LEFT JOIN freedomain f
ON t.email_domain ILIKE CONCAT('%', f.domain, '%');
旁注:
使用 ILIKE 时,无需降低 email_domain 列,因为比较已经是 case-insensitive.
样本:
CREATE OR REPLACE TABLE freedomain
AS
SELECT 'gmail' AS domain
UNION SELECT 'yahoo'
UNION SELECT 'hotmail';
CREATE OR REPLACE TABLE test
AS
SELECT 'biz' AS email_domain
UNION SELECT 'hotmail';
输出:
EMAIL_DOMAIN EMAIL_TYPE
hotmail free
biz business
Lukas 的回答很可靠,但为了避免必须将通配符标记 %
添加到域中,您可以使用 RLIKE,这是一个“类似正则表达式”。
但它在默认形式中区分大小写,这是您不想要的:
SELECT DISTINCT t.*,
IFF( f.domain IS NOT NULL, 'free', 'busineess') AS email_type
FROM test t
LEFT JOIN freedomain f
ON t.email_domain RLIKE f.domain;
所以需要使用第二种形式添加不敏感标志'i'
SELECT DISTINCT t.*,
IFF( f.domain IS NOT NULL, 'free', 'busineess') AS email_type
FROM test t
LEFT JOIN freedomain f
ON RLIKE(t.email_domain , f.domain, 'i');
但确实不应该进行两端开放的匹配,因为 this.is.not.google.com.example.com
是一个有效的域,而不是 google.com
因此您的匹配应该是固定的或使用 ENDSWITH(但同样不区分大小写)
CREATE OR REPLACE TABLE freedomain AS
SELECT column1 as domain FROM VALUES
('gmail.com'),
('yahoo.com'),
('hotmail.com')
;
CREATE OR REPLACE TABLE test AS
SELECT column1 as email_domain FROM VALUES
('mybiz.com'),
('thisisnotgmail.com.example.com'),
('gmail.com'),
('hotmail.com')
;
SELECT DISTINCT t.*,
IFF( f.domain IS NOT NULL, 'free', 'busineess') AS email_type
FROM test t
LEFT JOIN freedomain f
ON RLIKE(t.email_domain , f.domain || '$', 'i');
或
SELECT DISTINCT t.*,
IFF( f.domain IS NOT NULL, 'free', 'busineess') AS email_type
FROM test t
LEFT JOIN freedomain f
ON t.email_domain LIKE '%' || f.domain;
EMAIL_DOMAIN
EMAIL_TYPE
gmail.com
free
hotmail.com
free
mybiz.com
busineess
thisisnotgmail.com.example.com
busineess
有一个电子邮件域列表并且想要标记 'free' 如果该域类似于免费域, 这适用于我这样的硬编码列表:
CASE WHEN lower(email_domain) ilike any ('%%gmail%%','%%yahoo%%', '%%hotmail%%') THEN 'free' else 'business' end
但我真正想做的是从不同 table 的列中获取免费域列表,看起来像这样:
| SUBSTRING_VALUE |
|:------------------|
| "gmail" |
| "hotmail" |
| "yahoo" |
我试过使用带有 listagg 或 arrayagg 的子查询,但它不起作用, 有什么办法吗?
使用JOIN
:
SELECT DISTINCT t.*,
CASE WHEN f.domain IS NOT NULL THEN 'free' ELSE 'business' END AS email_type
FROM test t
LEFT JOIN freedomain f
ON t.email_domain ILIKE CONCAT('%', f.domain, '%');
旁注: 使用 ILIKE 时,无需降低 email_domain 列,因为比较已经是 case-insensitive.
样本:
CREATE OR REPLACE TABLE freedomain
AS
SELECT 'gmail' AS domain
UNION SELECT 'yahoo'
UNION SELECT 'hotmail';
CREATE OR REPLACE TABLE test
AS
SELECT 'biz' AS email_domain
UNION SELECT 'hotmail';
输出:
EMAIL_DOMAIN EMAIL_TYPE
hotmail free
biz business
Lukas 的回答很可靠,但为了避免必须将通配符标记 %
添加到域中,您可以使用 RLIKE,这是一个“类似正则表达式”。
但它在默认形式中区分大小写,这是您不想要的:
SELECT DISTINCT t.*,
IFF( f.domain IS NOT NULL, 'free', 'busineess') AS email_type
FROM test t
LEFT JOIN freedomain f
ON t.email_domain RLIKE f.domain;
所以需要使用第二种形式添加不敏感标志'i'
SELECT DISTINCT t.*,
IFF( f.domain IS NOT NULL, 'free', 'busineess') AS email_type
FROM test t
LEFT JOIN freedomain f
ON RLIKE(t.email_domain , f.domain, 'i');
但确实不应该进行两端开放的匹配,因为 this.is.not.google.com.example.com
是一个有效的域,而不是 google.com
因此您的匹配应该是固定的或使用 ENDSWITH(但同样不区分大小写)
CREATE OR REPLACE TABLE freedomain AS
SELECT column1 as domain FROM VALUES
('gmail.com'),
('yahoo.com'),
('hotmail.com')
;
CREATE OR REPLACE TABLE test AS
SELECT column1 as email_domain FROM VALUES
('mybiz.com'),
('thisisnotgmail.com.example.com'),
('gmail.com'),
('hotmail.com')
;
SELECT DISTINCT t.*,
IFF( f.domain IS NOT NULL, 'free', 'busineess') AS email_type
FROM test t
LEFT JOIN freedomain f
ON RLIKE(t.email_domain , f.domain || '$', 'i');
或
SELECT DISTINCT t.*,
IFF( f.domain IS NOT NULL, 'free', 'busineess') AS email_type
FROM test t
LEFT JOIN freedomain f
ON t.email_domain LIKE '%' || f.domain;
EMAIL_DOMAIN | EMAIL_TYPE |
---|---|
gmail.com | free |
hotmail.com | free |
mybiz.com | busineess |
thisisnotgmail.com.example.com | busineess |