【问题标题】:Hive Query Language return only values where NOT LIKE a value in another tableHive 查询语言仅返回 NOT LIKE 另一个表中的值的值
【发布时间】:2015-04-25 15:55:49
【问题描述】:

我正在尝试查找我的 hosts 表中的所有值,这些值不包含与我的 maildomains 表中的值的部分匹配。

hosts
+-------------------+-------+
|       host        | score |
+-------------------+-------+
| www.gmail.com     |   489 |
| www.hotmail.com   |   653 |
| www.google.com    |   411 |
| w3.hotmail.ca     |   223 |
| stackexchange.com |   950 |
+-------------------+-------+
maildomains 
+---------------+
| email         |
+---------------+
| gmail         |
| hotmail       |
| outlook       |
| mail          |
+---------------+

具体来说,我希望 SELECT * of hosts.host 不喜欢 '%.maildomains.email%' 中的任何值

Desired output:
+-------------------+-------+
|       host        | score |
+-------------------+-------+
| www.google.com    |   411 |
| stackexchange.com |   950 |
+-------------------+-------+

以下是我认为它在逻辑上应该如何工作:

SELECT h.*, m.email FROM (SELECT h.* FROM hosts WHERE score > 100 as h)
h LEFT OUTER JOIN maildomains m ON (h.host LIKE CONCAT('%.',m.email,'%'))
WHERE m.email IS NULL

这会导致错误 10017:join ''%'' 中遇到左右别名

我还设法让类似的查询像 CROSS JOIN 一样正常运行,但它会产生不好的结果:

SELECT h.*, m.email FROM (SELECT h.* FROM hosts WHERE score > 100 as h)
h CROSS JOIN maildomains m 
WHERE h.host NOT LIKE CONCAT('%.',m.email,'%')

+-------------------+---------+---------+
|      p.host       | p.score | m.email |
+-------------------+---------+---------+
| www.gmail.com     |     489 | hotmail |
| www.gmail.com     |     489 | outlook |
| www.gmail.com     |     489 | mail    |
| www.hotmail.com   |     653 | gmail   |
| www.hotmail.com   |     653 | outlook |
| www.hotmail.com   |     653 | mail    |
| www.google.com    |     411 | gmail   |
| www.google.com    |     411 | hotmail |
| www.google.com    |     411 | outlook |
| www.google.com    |     411 | mail    |
| w3.hotmail.ca     |     223 | gmail   |
| w3.hotmail.ca     |     223 | outlook |
| w3.hotmail.ca     |     223 | mail    |
| stackexchange.com |     950 | gmail   |
| stackexchange.com |     950 | hotmail |
| stackexchange.com |     950 | outlook |
| stackexchange.com |     950 | mail    |
+-------------------+---------+---------+

感谢所有指导。

【问题讨论】:

    标签: hadoop hive cloudera hiveql impala


    【解决方案1】:

    你可以这样做:

    select host from hosts h left outer join maildomains m on (regexp_replace(regexp_replace(regexp_replace(regexp_replace(h.host,'www.',''),'.com',''),'.ca',''),'w3.','') = m.email) where email is NULL;
    

    【讨论】:

      【解决方案2】:

      如果您的 Hive 版本是 0.13 或更高版本,则可以在 WHERE 子句中使用 subquery 来过滤来自 hosts 表的行。以下是一种更通用的方法,不需要您枚举您可能在数据中找到的所有顶级域:

      SELECT host, score
      FROM hosts
      WHERE
        regexp_extract(hosts.host, "(?:.*?\\.)?([^.]+)\\.[^.]+", 1) NOT IN
          (SELECT email FROM maildomains);
      

      这种方法使用regexp_extract 隔离TLD 之前的主机域部分,然后检查该域名是否出现在maildomains 表的子查询中。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2015-08-03
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-03-09
        • 1970-01-01
        相关资源
        最近更新 更多