Amazon RedshiftがQUALIFY句をサポート
分析(Window)関数の利便性大向上!

2023年7月27日掲載

governance

Amazon Redshift(以後Redshift)でもQUALIFY句が使えるようになりました。Google CloudのBigQueryなどでは既にサポートされており、AWSでの分析時にも使いたいと、熱烈に期待していました。

RedshiftでQUALIFY句をさっそく試してみましょう。

 

目次

QUALIFY句とは?

QUALIFY句は、SQLの構文要素の1つです。分析関数と組み合わせて使用し、結果セットをフィルタリングする機能です。複雑な条件やサブクエリを使用せずに、直感的で簡潔な構文を書けるようになります。

言葉だけでは理解しづらいこともありますので、説明はここまでにして、実際にQUALIFY句がサポートされたRedshift上でSELECT文を叩いてみましょう。

RedShiftで使ってみる

AWSのガイドに従って、操作していきます。

◆ テーブルの作成
適当な簡易的なテーブルを作成します。日時ごとのセールスデータです。

create table store_sales (
    ss_sold_date date, 
    ss_sold_time time, 
    ss_item text,
    ss_sales_price float);
insert into store_sales values 
  ('2022-01-01', '09:00:00', 'Product 1', 100.0),
  ('2022-01-01', '11:00:00', 'Product 2', 500.0),
  ('2022-01-01', '15:00:00', 'Product 3', 20.0),
  ('2022-01-01', '17:00:00', 'Product 4', 1000.0),
  ('2022-01-01', '18:00:00', 'Product 5', 30.0),
  ('2022-01-02', '10:00:00', 'Product 6', 5000.0),
  ('2022-01-02', '16:00:00', 'Product 7', 5.0);

 

◆ 分析関数にQUALIFY句を適用しSELECT
作成したテーブルを対象に、いよいよ、QUALIFY句を使ったSELECT文を実行します。

(例1)各販売日ごとに売上価格が上位2つの商品の情報を取得
データを日付ごとにグループ化します。それぞれのグループ内で売上金額の降順にソートし、上位2つの行を取得します。
WHERE句は最終出力を絞るためであり、分析関数の本質的な目的ではありません。

SELECT *
FROM store_sales
WHERE ss_sold_time > time '12:00:00'
QUALIFY row_number()
OVER (PARTITION BY ss_sold_date ORDER BY ss_sales_price DESC) <= 2

ss_sold_date | ss_sold_time |  ss_item  | ss_sales_price 
--------------+--------------+-----------+----------------
 2022-01-01   | 17:00:00     | Product 4 |           1000
 2022-01-01   | 18:00:00     | Product 5 |             30
 2022-01-02   | 16:00:00     | Product 7 |              5

PARTITION BY句によって、ss_sold_dateの値で、ss_sold_dateごとに独立したグループが形成されます。

ORDER BY句によって、ss_sales_priceが降順(DESC)でソートされます。このソートは各グループ内で独立して行われます。

row_number()関数によって、各行に対して行番号が計算されます。行番号は、グループ内でのソート順に基づいて付与されます。

最後にQUALIFY句が適用されます。QUALIFY句は、条件を指定して結果セットをフィルタリングするための機能です。<=2を指定しています。この場合、row_number()の値が2以下の行(各グループ内でss_sales_priceが高い行から2つ)のみが結果として残ります。

 

QUALIFY句が使えないとこういったクエリになります。

SELECT *
FROM (
  SELECT *,
         row_number() OVER (PARTITION BY ss_sold_date ORDER BY ss_sales_price DESC) 
  FROM store_sales
  WHERE ss_sold_time > time '12:00:00'
) AS subquery
WHERE row_num <= 2;

 

もう一つ見ておきましょう。
(例2)各販売日ごとに最後の販売時間のss_itemと同じ値を持つ情報の取得

SELECT *
FROM store_sales
QUALIFY last_value(ss_item)
OVER (PARTITION BY ss_sold_date ORDER BY ss_sold_time ASC
      ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) = ss_item;
               
ss_sold_date | ss_sold_time |  ss_item  | ss_sales_price 
--------------+--------------+-----------+----------------
 2022-01-01   | 18:00:00     | Product 5 |             30
 2022-01-02   | 16:00:00     | Product 7 |              5 

PARTITION BY句によって、ss_sold_dateの値でグループ分けされます。

ORDER BY句によって、グループ内ごとに、ss_sold_timeで昇順(ASC)ソートされます。

ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWINGは範囲指定子です。UNBOUNDEDとしているので、ウィンドウで区切ったグループ全体が集計対象です。

last_value(ss_item)関数によって、ss_item列の最後の値が取得されます。

最後に、QUALIFY句が適用されます。last_value(ss_item)の値がss_item列の値と等しい行のみが結果として残ります。各ss_sold_dateごとに、ss_sold_timeの最後の1行と、その行のss_itemの値が一致する行のみを抽出するということです。


QUALIFY句を使えない場合はどうなるかをここでも示しておきます。

SELECT * FROM (
  SELECT *,
  last_value(ss_item)
  OVER (PARTITION BY ss_sold_date ORDER BY ss_sold_time ASC
        ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) ss_last_item
  FROM store_sales
)
WHERE ss_last_item = ss_item;

QUALIFYが使えないと、WHERE句を使用することになるため、サブクエリなどを使用したネスト構文になります。

まとめ

Redshiftで、QUALIFY句がサポートされました。
QUALIFY句の利用により、複雑な条件を簡潔なコードで表現できるようになりました。データ分析の可読性や開発効率が向上することでしょう。Redshiftの強力な分析機能を最大限に活かしてみてください。

関連サービス

Amazon Web Services (AWS)

ソフトバンクはAWS アドバンストティアサービスパートナーです。「はじめてのAWS導入」から大規模なサービス基盤や基幹システムの構築まで、お客さまのご要望にあわせて最適なAWS環境の導入を支援します。

おすすめの記事

条件に該当するページがございません