簡體   English   中英

如何在 case 中使用計數

[英]how to use count with case when

我是 Hivesql 的新手。 我有一個包含 600 萬條記錄的原始表,如下所示:

數據表

我想每周計算每個 Modem_id 的 IP_address 訪問次數。 我想要的結果表是這樣的:

結果表

我用左連接做到了,它奏效了。 但是由於使用 join 會很耗時,我想用 case when 語句來做 - 但我不能寫出正確的語句。 你有什么想法?

這是我使用的連接語句:

select a.modem_id, 
       a.Number_of_IP_in_Day_1, 
       b.Number_of_IP_in_Day_2
from 
(select modem_id,
        count(distinct ip_address) as Number_of_IP_in_Day_1 
  from F_ACS_DEVICE_INFORMATION_NEW 
  where day=1
  group by modem_id) a 
left join 
(select modem_id,
        count(distinct param_value) as Number_of_IP_in_Day_2 
  from F_ACS_DEVICE_INFORMATION_NEW 
  where day=2
  group by modem_id) b 
on a.modem_id= b.modem_id; 

根據您的問題和進一步的評論,您希望

  • 每個調制解調器訪問的不同 IP 地址的數量
  • 在 4 周內按周計數(作為列)

例如,結果將是 5 列

  • 調制解調器 ID
  • IPs_accessed_week1
  • IPs_accessed_week2
  • IPs_accessed_week3
  • IPs_accessed_week4

我的答案是基於 SQL 的知識——我沒有使用過 Hive,但它似乎支持我使用的東西(例如,CTE)。 您可能需要稍微調整一下答案。

第一個關鍵步驟是將 day_number 轉換為 week_number。 一個簡單的方法是FLOOR((day_num-1)/7)+1所以第 1-7 天變成第 1 周,第 8-14 天變成第 2 周,依此類推。

注意 - 由您來確保 day_nums 是正確的。 我猜你實際上想要的是過去4 周的信息,而不是前 4 周的數據——因此你可能會將 day_num 計算為類似於SELECT DATEDIFF(day, IP_access_date, CAST(getdate() AS date)) - 無論在 Hive 中的等價物是什么。

有幾種方法可以做到這一點 - 我認為最清楚的是使用 CTE 將您的數據集轉換為您需要的數據,例如,

  • 將 day_nums 轉換為 weeknums
  • 在一周內擺脫重復項(您的代碼有COUNT(DISTINCT ...) - 我認為這就是您想要的) - 我正在使用 SELECT DISTINCT (而不是按所有字段分組)

從那里,您可以 PIVOT 數據以將其放入您的表中,或者僅使用 CASE 語句的 SUM。 我將在這里使用 CASE 的總和,因為我認為它更容易理解。

WITH IPs_per_week AS
    (SELECT DISTINCT 
            modem_id,
            ip_address,
            FLOOR((day-1)/7)+1 AS week_num    -- Note I've referred to it as day_num in text for clarity
     FROM   F_ACS_DEVICE_INFORMATION_NEW
    )
SELECT modem_id,
       SUM(CASE WHEN week_num = 1 THEN 1 ELSE 0 END) AS IPs_access_week1,
       SUM(CASE WHEN week_num = 2 THEN 1 ELSE 0 END) AS IPs_access_week2,
       SUM(CASE WHEN week_num = 3 THEN 1 ELSE 0 END) AS IPs_access_week3,
       SUM(CASE WHEN week_num = 4 THEN 1 ELSE 0 END) AS IPs_access_week4
FROM   IPs_per_week
GROUP BY modem_id;

您可以僅使用聚合來表達您的邏輯:

select a.modem_id, 
       count(distinct case when date = 1 then ip_address end) as day_1,
       count(distinct case when date = 2 then ip_address end) as day_2
from F_ACS_DEVICE_INFORMATION_NEW a
group by a.modem_id;

您顯然可以將其延長更多天。

注意:在編寫您的問題和代碼時,這里假設您的基表只有一周的數據。 否則,我希望有一些日期過濾。 據推測,這就是表名上的_NEW后綴的含義。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM