对来自不同 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