こんにちは、ドイです! 前回に引き続き、データサイエンス100本ノックに挑戦していきます。
前回の記事
S-036: レシート明細データ(receipt)と店舗データ(store)を内部結合し、レシート明細データの全項目と店舗データの店舗名(store_name)を10件表示せよ。
SELECT receipt.*, store.store_name FROM receipt JOIN store ON receipt.store_cd = store.store_cd LIMIT 10;
S-037: 商品データ(product)とカテゴリデータ(category)を内部結合し、商品データの全項目とカテゴリデータのカテゴリ小区分名(category_small_name)を10件表示せよ。
SELECT product.*, category.category_small_name FROM product JOIN category ON product.category_small_cd = category.category_small_cd LIMIT 10;
S-038: 顧客データ(customer)とレシート明細データ(receipt)から、顧客ごとの売上金額合計を求め、10件表示せよ。ただし、売上実績がない顧客については売上金額を0として表示させること。また、顧客は性別コード(gender_cd)が女性(1)であるものを対象とし、非会員(顧客IDが\"Z\"から始まるもの)は除外すること。
WITH customer_amount AS ( SELECT customer_id, SUM(amount) AS sum_amount FROM receipt GROUP BY customer_id ) SELECT customer.customer_id, COALESCE(customer_amount.sum_amount,0) FROM customer LEFT JOIN customer_amount ON customer.customer_id = customer_amount.customer_id WHERE customer.gender_cd = '1' and customer.customer_id NOT LIKE 'Z%' LIMIT 10;
LEFT JOIN (左外部結合)
問題文に「ただし、売上実績がない顧客については売上金額を0として表示させること。」とあります。
つまり、顧客データ(customer)に存在するが、レシート明細データ(receipt)にはデータが存在しない顧客データを取得する必要があります。先に指定したテーブルに存在して、後に指定したテーブルにはないデータも含めて取得する必要があるので、この問題では LEFT JOIN (左外部結合)しています。
S-039: レシート明細データ(receipt)から、売上日数の多い顧客の上位20件を抽出したデータと、売上金額合計の多い顧客の上位20件を抽出したデータをそれぞれ作成し、さらにその2つを完全外部結合せよ。ただし、非会員(顧客IDが\"Z\"から始まるもの)は除外すること。
WITH days AS ( SELECT customer_id, COUNT(DISTINCT(sales_ymd)) count_ymd FROM receipt WHERE customer_id NOT LIKE 'Z%' GROUP BY customer_id ORDER BY count_ymd DESC LIMIT 20 ), amount AS ( SELECT customer_id, SUM(amount) sum_amount FROM receipt WHERE customer_id NOT LIKE 'Z%' GROUP BY customer_id ORDER BY sum_amount DESC LIMIT 20 ) SELECT COALESCE(days.customer_id, amount.customer_id), days.count_ymd, amount.sum_amount FROM days FULL JOIN amount ON days.customer_id = amount.customer_id;
FULL JOIN(完全外部結合)
問題文にある通り「完全外部結合せよ」とあります。
この問題では
①売上日数の多い顧客の上位20件を抽出したデータ
②売上金額合計の多い顧客の上位20件を抽出したデータ
を取得する必要があります。
①のみに該当するデータ
②のみに該当するデータ
①と②どちらにも該当するデータの3パターンが取得の対象です。
LEFT JOIN (左外部結合)では「先に指定したテーブルに存在して、後に指定したテーブルにはないデータも含めて取得」しますが、FULL JOIN(完全外部結合)は、「先に指定したテーブルにしか存在しないデータ、後に指定したテーブルにしか存在しないデータの両方を取得」することができます。
S-040: 全ての店舗と全ての商品を組み合わせたデータを作成したい。店舗データ(store)と商品データ(product)を直積し、件数を計算せよ。
SELECT COUNT(1) FROM store CROSS JOIN product;
CROSS JOIN(クロス結合)
指定した全ての組み合わせのデータを取得して、全ての組み合わせで結合します。数学の確立のようですね。(サイコロ問題のような…)
まとめ
今回は結合に関する問題が多くありました。問題を正しく理解しないと、どう結合すればいいのか悩んでしまいますね。
次回も引き続き頑張っていきます!!