我正在查看我們在 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;
我已經更改了名稱,但這是用于將覆寫插入另一個表的選擇陳述句。關于加盟
join (
select * from second
) b on a.c_id = b.c_id
除了連接條件之外,b 沒有在任何地方使用,那么這個連接是否有任何目的?
是為了確保此聯接僅具有第二個表中存在 c_id 的條目嗎?如果這一切都在做,where IN 條件會更好。或者我可以洗掉這個連接,它根本不會有任何區別。
謝謝。
uj5u.com熱心網友回復:
- 如果連接資料集中的連接鍵不唯一,則連接(任何內部、左側或右側)可以復制行。例如,如果
a包含帶有 的單行c_id=1并且b包含帶有 的兩行c_id=1,則結果將是帶有 的兩行a.c_id=1。 - 如果連接資料集中沒有連接鍵,則連接(內部)可以過濾行。我相信這就是它的意思。
如果目標是只獲取兩個資料集中都存在鍵的行(過濾器)并且您不希望重復,并且您不使用連接資料集中的列,那么最好使用 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)
或相關的存在:
WHERE EXISTS (select 1 from second b where a.c_id=b.c_id)
但正如我所說,所有這些都是使用 JOIN 運算子在內部實作的。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/415581.html
標籤:
