Hiveを用いた前年比・前月比の計算手法

前年比と前月比の計算方法

データ分析において、時間軸に沿った指標の変化を評価するためには「前年比(Year-on-Year)」や「前月比(Month-on-Month)」の計算が不可欠です。Hiveでは、これらの指標をウィンドウ関数や自己結合を活用して効率的に算出できます。

テストデータの準備

以下の売上データを使用します。

1,2020-04-20,420
2,2020-04-04,800
3,2020-03-28,500
4,2020-03-13,100
5,2020-02-27,300
6,2020-01-07,450
7,2019-04-07,800
8,2019-03-15,1200
9,2019-02-17,200
10,2019-02-07,600
11,2019-01-13,300

Hiveでのテーブル作成とデータ読み込みは次の通りです。

CREATE TABLE sales_data (
  id INT,
  sale_date DATE,
  amount INT
)
ROW FORMAT DELIMITED
FIELDS TERMINATED BY ',';

LOAD DATA LOCAL INPATH '/path/to/sales.txt' INTO TABLE sales_data;

月次売上の年間比率計算

各月の売上がその年に占める割合を求める場合、サブクエリによる集計結合またはウィンドウ関数で実現可能です。

方法1:サブクエリによる内部結合

SELECT 
  monthly.month_label,
  monthly.month_total,
  yearly.year_total,
  ROUND(monthly.month_total / yearly.year_total, 4) AS proportion
FROM (
  SELECT 
    SUM(amount) AS month_total,
    DATE_FORMAT(sale_date, 'yyyy-MM') AS month_label
  FROM sales_data
  GROUP BY DATE_FORMAT(sale_date, 'yyyy-MM')
) monthly
JOIN (
  SELECT 
    SUM(amount) AS year_total,
    DATE_FORMAT(sale_date, 'yyyy') AS year_label
  FROM sales_data
  GROUP BY DATE_FORMAT(sale_date, 'yyyy')
) yearly
ON SUBSTR(monthly.month_label, 1, 4) = yearly.year_label;

方法2:ウィンドウ関数による一括処理

WITH base AS (
  SELECT 
    SUBSTR(sale_date, 1, 7) AS month_str,
    SUM(amount) OVER (PARTITION BY SUBSTR(sale_date, 1, 7)) AS m_amount,
    SUM(amount) OVER (PARTITION BY SUBSTR(sale_date, 1, 4)) AS y_amount,
    ROW_NUMBER() OVER (PARTITION BY SUBSTR(sale_date, 1, 7)) AS rn
  FROM sales_data
)
SELECT 
  month_str,
  m_amount,
  y_amount,
  ROUND(m_amount * 1.0 / y_amount, 4) AS ratio
FROM base
WHERE rn = 1
ORDER BY month_str;

前年比・前月比の計算

成長率の基本式は以下の通りです。

  • 前年比 = (当期値 - 前年同月値) / 前年同月値 × 100%
  • 前月比 = (当月値 - 前月値) / 前月値 × 100%

ウィンドウ関数LAGを使ったアプローチ

直近の過去値を取得するためにLAG()関数を利用できます。ただし、データに欠損がある場合、誤った期間の値を参照してしまう可能性があります。

WITH monthly_summary AS (
  SELECT 
    SUBSTR(sale_date, 1, 7) AS current_month,
    SUM(amount) AS current_value
  FROM sales_data
  GROUP BY SUBSTR(sale_date, 1, 7)
),
lagged_data AS (
  SELECT 
    current_month,
    current_value,
    LAG(current_value, 1, 0) OVER (ORDER BY current_month) AS prev_value
  FROM monthly_summary
)
SELECT 
  current_month,
  current_value,
  prev_value,
  CASE 
    WHEN prev_value = 0 THEN NULL 
    ELSE ROUND((current_value - prev_value) * 1.0 / prev_value, 4) 
  END AS mom_growth_rate
FROM lagged_data;

この結果は、連続した月データがない場合に不正確になるため、より厳密な日付演算が必要です。

自己結合による正確な前月比計算

月単位の差分を明示的に計算することで、欠損のあるデータに対しても正確な比較が可能になります。

WITH monthly_stats AS (
  SELECT 
    SUBSTR(sale_date, 1, 7) AS base_month,
    SUM(amount) AS total_amount
  FROM sales_data
  GROUP BY SUBSTR(sale_date, 1, 7)
),
with_prev_month AS (
  SELECT 
    base_month,
    total_amount,
    ADD_MONTHS(CONCAT(base_month, '-01'), -1) AS prior_month_date
  FROM monthly_stats
)
SELECT 
  curr.base_month AS this_month,
  curr.total_amount AS current_sales,
  prev.base_month AS last_month,
  prev.total_amount AS previous_sales,
  CASE 
    WHEN prev.total_amount IS NULL OR prev.total_amount = 0 THEN 0.0
    ELSE ROUND((curr.total_amount - prev.total_amount) * 1.0 / prev.total_amount, 4)
  END AS growth_rate
FROM with_prev_month curr
LEFT JOIN monthly_stats prev
ON SUBSTR(curr.prior_month_date, 1, 7) = prev.base_month
ORDER BY curr.base_month;

この方式では、ADD_MONTHS関数を使って正確に1か月前の日付を生成し、文字列として比較しているため、時間軸の整合性を保ちながら安全に前月比を算出できます。

タグ: Hive 前年比 前月比 ウィンドウ関数 ADD_MONTHS

8月14日 15:58 投稿