2012-10-31 82 views
0

我有一個大型的事件表。每個用戶我想計算在最早的B型事件之前發生的A類事件。如何在Hive/SQL中的where/having子句(避免子查詢)中使用min()

我正在尋找一個優雅的查詢。蜂巢使用,所以我不能做子查詢

Timestamp Type User 
...  A X 
...  A X 
...  B X 
...  A X 
...  A X 

...  A Y 
...  A Y 
...  A Y 
...  B Y 
...  A Y 

通緝的結果:

User Count_Type_A 
X 2 
Y 3 

我不能做讓「切斷」時間戳:

Select User, min(Timestamp) 
Where Type=B 
Group BY User; 

但隨後如何在下一個查詢中使用該信息,並在其中執行以下操作:

SELECT User, count(Timestamp) 
WHERE Type=A AND Timestamp<min(User.Timestamp_Type_B) 
GROUP BY User; 

我到目前爲止唯一的想法是首先確定截止時間戳,然後與所有類型A事件進行連接,然後從結果表中進行選擇,但感覺錯誤並且看起來很醜。

我也在考慮這是Hive的錯誤類型的問題/分析,我應該考慮用手寫的map-reduce或pig代替。

請通過指向正確的方向來幫助我。

回答

1

首先更新:

針對Cilvic首款這個答案的評論,我已經調整了我的查詢到基於意見建議的解決方法在https://issues.apache.org/jira/browse/HIVE-556發現如下:

SELECT [User], COUNT([Timestamp]) AS [Before_First_B_Count] 
FROM [Dataset] main 
CROSS JOIN (SELECT [User], min([Timestamp]) [First_B_TS] FROM [Dataset] 
    WHERE [Type] = 'B' 
    GROUP BY [User]) sub 
WHERE main.[Type] = 'A' 
AND (sub.[User] = main.[User]) 
AND (main.[Timestamp] < sub.[First_B_TS]) 
GROUP BY main.[User] 

原創:

給這個鏡頭:

SELECT [User], COUNT([Timestamp]) AS [Before_First_B_Count] 
FROM [Dataset] main 
JOIN (SELECT [User], min([Timestamp]) [First_B_TS] FROM [Dataset] 
    WHERE [Type] = 'B' 
    GROUP BY [User]) sub 
     ON (sub.[User] = main.[User]) AND (main.[Timestamp] < sub.[First_B_TS]) 
WHERE main.[Type] = 'A' 
GROUP BY main.[User] 

我盡我所能地遵循蜂巢語法。如果您有任何問題,請告訴我。我想知道爲什麼你希望/需要避免子查詢。

+0

我發現蜂巢(遺憾的是不支持<加盟條件:「只有平等連接,外連接,並留下半聯接在蜂巢支持蜂房不支持加入不在平等條件,因爲它的條件。 「https://cwiki.apache.org/Hive/languagemanual-joins.html – Cilvic

+0

我很抱歉,我又做了一次嘗試,請讓我知道它是否有效。簡而言之,我將ON語句移到了WHERE子句,並使(INNER)JOIN成爲CROSS JOIN。 –

1

一般來說,I + 1 coge.soft的解決方案。這又是供你參考:

SELECT [User], COUNT([Timestamp]) AS [Before_First_B_Count] 
FROM [Dataset] main 
JOIN (SELECT [User], min([Timestamp]) [First_B_TS] FROM [Dataset] 
    WHERE [Type] = 'B' 
    GROUP BY [User]) sub 
     ON (sub.[User] = main.[User]) AND (main.[Timestamp] < sub.[First_B_TS]) 
WHERE main.[Type] = 'A' 
GROUP BY main.[User] 

然而,有兩件事情需要注意:

  1. 什麼時候有沒有B事件發生?假設你想在這種情況下計算每個用戶的所有A事件,那麼解決方案中指定的內部連接將不起作用,因爲子表中沒有該用戶的條目。您需要爲此更改爲左外連接。

  2. 該解決方案還會傳遞數據 - 一個填充子表,另一個將子表連接到主表。根據您的性能和效率的概念,您可以通過一次數據傳輸來實現這一點。您可以通過用戶使用Hive的distribute by功能分發數據,並編寫自定義縮減程序,使用Hive's transform functionality以您最喜歡的語言進行計算。

+0

通過聲音分配真的很有趣!非常感謝! – Cilvic

+0

@Cilvic,是上面第二點爲什麼你試圖避免子查詢(根據您的問題的標題)? –

+0

@ coge.so英尺不知道我明白你的觀點。我認爲你提出的解決方案有效。但同時它很難理解/閱讀。我希望找到更優雅/更易於閱讀的東西。我需要先了解更好地分配。 – Cilvic