没有使用 2nd table 中的列的 JOIN 的目的是什么?
What's the purpose of a JOIN where no column from 2nd table is being used?
我正在查看我们 运行 作为 hadoop 集群分析的一部分的一些配置单元查询,但我无法理解其中的一个。这是 Hive QL 查询
SELECT
c_id, v_id, COUNT(DISTINCT(m_id)) AS participants,
cast(date_sub(current_date, ${window}) as string) as event_date
from (
select
a.c_id, a.v_id, a.user_id,
case
when c.id1 is not null and a.timestamp <= c.stitching_ts then c.id2 else a.m_id
end as m_id
from (
select * from first
where event_date <= cast(date_sub(current_date, ${window}) as string)
) a
join (
select * from second
) b on a.c_id = b.c_id
left join third c
on a.user_id = c.id1
) dx
group by c_id, v_id;
我已经更改了名称,但除此之外,这是 select 用于插入覆盖另一个 table 的语句。
关于加入
join (
select * from second
) b on a.c_id = b.c_id
b 除了连接条件外没有在任何地方使用,那么这个连接是否有任何用途?
是为了确保此连接仅包含 c_id 出现在第二个 table 中的条目吗?如果这一切都在做,那么 where IN 条件会更好吗?
或者我可以只删除此连接,它根本不会产生任何影响。
谢谢。
- 如果连接数据集中的连接键不唯一,则连接(任何内部、左侧或右侧)可以复制行。例如,如果
a
包含带有 c_id=1
的单行并且 b
包含带有 c_id=1
的两行,则结果将是带有 a.c_id=1
.[=34= 的两行]
- 如果连接数据集中没有连接键,连接(内部)可以过滤行。我相信这就是它的本意。
如果目标是仅获取具有两个数据集(过滤器)中存在的键的行并且您不想重复,并且您不使用连接数据集中的列,那么最好使用 LEFT SEMI JOIN 而不是 JOIN,它仅当连接数据集中存在重复键时才用作过滤器:
left semi join (
select c_id from second
) b on a.c_id = b.c_id
这是一种更安全的方法,可以仅过滤同时存在于 a 和 b 中的行并避免意外重复。
你可以用 WHERE IN/EXISTS 代替 join,但没有区别,它实现为相同的 JOIN,检查 EXPLAIN 输出,你会看到相同的查询计划。最好使用 LEFT SEMI JOIN,它以有效的方式实现不相关 IN/EXISTS。
如果您希望将其移动到 WHERE:
WHERE a.c_id IN (select c_id from second)
或相关的 EXISTS:
WHERE EXISTS (select 1 from second b where a.c_id=b.c_id)
但正如我所说,所有这些都是使用 JOIN 运算符在内部实现的。
我正在查看我们 运行 作为 hadoop 集群分析的一部分的一些配置单元查询,但我无法理解其中的一个。这是 Hive QL 查询
SELECT
c_id, v_id, COUNT(DISTINCT(m_id)) AS participants,
cast(date_sub(current_date, ${window}) as string) as event_date
from (
select
a.c_id, a.v_id, a.user_id,
case
when c.id1 is not null and a.timestamp <= c.stitching_ts then c.id2 else a.m_id
end as m_id
from (
select * from first
where event_date <= cast(date_sub(current_date, ${window}) as string)
) a
join (
select * from second
) b on a.c_id = b.c_id
left join third c
on a.user_id = c.id1
) dx
group by c_id, v_id;
我已经更改了名称,但除此之外,这是 select 用于插入覆盖另一个 table 的语句。 关于加入
join (
select * from second
) b on a.c_id = b.c_id
b 除了连接条件外没有在任何地方使用,那么这个连接是否有任何用途?
是为了确保此连接仅包含 c_id 出现在第二个 table 中的条目吗?如果这一切都在做,那么 where IN 条件会更好吗?
或者我可以只删除此连接,它根本不会产生任何影响。
谢谢。
- 如果连接数据集中的连接键不唯一,则连接(任何内部、左侧或右侧)可以复制行。例如,如果
a
包含带有c_id=1
的单行并且b
包含带有c_id=1
的两行,则结果将是带有a.c_id=1
.[=34= 的两行] - 如果连接数据集中没有连接键,连接(内部)可以过滤行。我相信这就是它的本意。
如果目标是仅获取具有两个数据集(过滤器)中存在的键的行并且您不想重复,并且您不使用连接数据集中的列,那么最好使用 LEFT SEMI JOIN 而不是 JOIN,它仅当连接数据集中存在重复键时才用作过滤器:
left semi join (
select c_id from second
) b on a.c_id = b.c_id
这是一种更安全的方法,可以仅过滤同时存在于 a 和 b 中的行并避免意外重复。
你可以用 WHERE IN/EXISTS 代替 join,但没有区别,它实现为相同的 JOIN,检查 EXPLAIN 输出,你会看到相同的查询计划。最好使用 LEFT SEMI JOIN,它以有效的方式实现不相关 IN/EXISTS。
如果您希望将其移动到 WHERE:
WHERE a.c_id IN (select c_id from second)
或相关的 EXISTS:
WHERE EXISTS (select 1 from second b where a.c_id=b.c_id)
但正如我所说,所有这些都是使用 JOIN 运算符在内部实现的。