%load_ext sql
import os
from sqlalchemy import create_engine
pgconfig = {
'host': 'db',
'port': os.environ['PG_PORT'],
'database': os.environ['PG_DATABASE'],
'user': os.environ['PG_USER'],
'password': os.environ['PG_PASSWORD'],
}
dsl = 'postgresql://{user}:{password}@{host}:{port}/{database}'.format(**pgconfig)
conn = create_engine(dsl)
# MagicコマンドでSQLを書くための設定
%sql conn
'Connected: padawan@dsdojo_db'
%%sql
SELECT 'このように実行できます' AS sample;
* postgresql://padawan:***@db:5432/dsdojo_db 1 rows affected.
| sample |
|---|
| このように実行できます |
S-001: レシート明細データ(receipt)から全項目の先頭10件を表示し、どのようなデータを保有しているか目視で確認せよ。
%%sql
SELECT
*
FROM receipt
LIMIT 10
;
* postgresql://padawan:***@db:5432/dsdojo_db 10 rows affected.
| sales_ymd | sales_epoch | store_cd | receipt_no | receipt_sub_no | customer_id | product_cd | quantity | amount |
|---|---|---|---|---|---|---|---|---|
| 20181103 | 1541203200 | S14006 | 112 | 1 | CS006214000001 | P070305012 | 1 | 158 |
| 20181118 | 1542499200 | S13008 | 1132 | 2 | CS008415000097 | P070701017 | 1 | 81 |
| 20170712 | 1499817600 | S14028 | 1102 | 1 | CS028414000014 | P060101005 | 1 | 170 |
| 20190205 | 1549324800 | S14042 | 1132 | 1 | ZZ000000000000 | P050301001 | 1 | 25 |
| 20180821 | 1534809600 | S14025 | 1102 | 2 | CS025415000050 | P060102007 | 1 | 90 |
| 20190605 | 1559692800 | S13003 | 1112 | 1 | CS003515000195 | P050102002 | 1 | 138 |
| 20181205 | 1543968000 | S14024 | 1102 | 2 | CS024514000042 | P080101005 | 1 | 30 |
| 20190922 | 1569110400 | S14040 | 1102 | 1 | CS040415000178 | P070501004 | 1 | 128 |
| 20170504 | 1493856000 | S13020 | 1112 | 2 | ZZ000000000000 | P071302010 | 1 | 770 |
| 20191010 | 1570665600 | S14027 | 1102 | 1 | CS027514000015 | P071101003 | 1 | 680 |
S-002: レシート明細データ(receipt)から売上年月日(sales_ymd)、顧客ID(customer_id)、商品コード(product_cd)、売上金額(amount)の順に列を指定し、10件表示せよ。
%%sql
SELECT
sales_ymd,
customer_id,
product_cd,
amount
FROM receipt
LIMIT 10
;
* postgresql://padawan:***@db:5432/dsdojo_db 10 rows affected.
| sales_ymd | customer_id | product_cd | amount |
|---|---|---|---|
| 20181103 | CS006214000001 | P070305012 | 158 |
| 20181118 | CS008415000097 | P070701017 | 81 |
| 20170712 | CS028414000014 | P060101005 | 170 |
| 20190205 | ZZ000000000000 | P050301001 | 25 |
| 20180821 | CS025415000050 | P060102007 | 90 |
| 20190605 | CS003515000195 | P050102002 | 138 |
| 20181205 | CS024514000042 | P080101005 | 30 |
| 20190922 | CS040415000178 | P070501004 | 128 |
| 20170504 | ZZ000000000000 | P071302010 | 770 |
| 20191010 | CS027514000015 | P071101003 | 680 |
S-003: レシート明細データ(receipt)から売上年月日(sales_ymd)、顧客ID(customer_id)、商品コード(product_cd)、売上金額(amount)の順に列を指定し、10件表示せよ。ただし、sales_ymdsales_dateに項目名を変更しながら抽出すること。
%%sql
SELECT
sales_ymd AS sales_date,
customer_id,
product_cd,
amount
FROM receipt
LIMIT 10
;
* postgresql://padawan:***@db:5432/dsdojo_db 10 rows affected.
| sales_date | customer_id | product_cd | amount |
|---|---|---|---|
| 20181103 | CS006214000001 | P070305012 | 158 |
| 20181118 | CS008415000097 | P070701017 | 81 |
| 20170712 | CS028414000014 | P060101005 | 170 |
| 20190205 | ZZ000000000000 | P050301001 | 25 |
| 20180821 | CS025415000050 | P060102007 | 90 |
| 20190605 | CS003515000195 | P050102002 | 138 |
| 20181205 | CS024514000042 | P080101005 | 30 |
| 20190922 | CS040415000178 | P070501004 | 128 |
| 20170504 | ZZ000000000000 | P071302010 | 770 |
| 20191010 | CS027514000015 | P071101003 | 680 |
S-004: レシート明細データ(receipt)から売上日(sales_ymd)、顧客ID(customer_id)、商品コード(product_cd)、売上金額(amount)の順に列を指定し、以下の条件を満たすデータを抽出せよ。
- 顧客ID(customer_id)が"CS018205000001"
%%sql
SELECT
sales_ymd,
customer_id,
product_cd,
amount
FROM
receipt
WHERE
customer_id = 'CS018205000001'
;
* postgresql://padawan:***@db:5432/dsdojo_db 12 rows affected.
| sales_ymd | customer_id | product_cd | amount |
|---|---|---|---|
| 20180911 | CS018205000001 | P071401012 | 2200 |
| 20180414 | CS018205000001 | P060104007 | 600 |
| 20170614 | CS018205000001 | P050206001 | 990 |
| 20170614 | CS018205000001 | P060702015 | 108 |
| 20190216 | CS018205000001 | P071005024 | 102 |
| 20180414 | CS018205000001 | P071101002 | 278 |
| 20190226 | CS018205000001 | P070902035 | 168 |
| 20190924 | CS018205000001 | P060805001 | 495 |
| 20190226 | CS018205000001 | P071401020 | 2200 |
| 20180911 | CS018205000001 | P071401005 | 1100 |
| 20190216 | CS018205000001 | P040101002 | 218 |
| 20190924 | CS018205000001 | P091503001 | 280 |
S-005: レシート明細データ(receipt)から売上日(sales_ymd)、顧客ID(customer_id)、商品コード(product_cd)、売上金額(amount)の順に列を指定し、以下の全ての条件を満たすデータを抽出せよ。
- 顧客ID(customer_id)が"CS018205000001"
- 売上金額(amount)が1,000以上
%%sql
SELECT
sales_ymd,
customer_id,
product_cd,
amount
FROM
receipt
WHERE
customer_id = 'CS018205000001'
AND amount >= 1000
;
* postgresql://padawan:***@db:5432/dsdojo_db 3 rows affected.
| sales_ymd | customer_id | product_cd | amount |
|---|---|---|---|
| 20180911 | CS018205000001 | P071401012 | 2200 |
| 20190226 | CS018205000001 | P071401020 | 2200 |
| 20180911 | CS018205000001 | P071401005 | 1100 |
S-006: レシート明細データ(receipt)から売上日(sales_ymd)、顧客ID(customer_id)、商品コード(product_cd)、売上数量(quantity)、売上金額(amount)の順に列を指定し、以下の全ての条件を満たすデータを抽出せよ。
- 顧客ID(customer_id)が"CS018205000001"
- 売上金額(amount)が1,000以上または売上数量(quantity)が5以上
%%sql
SELECT
sales_ymd,
customer_id,
product_cd,
quantity,
amount
FROM
receipt
WHERE
customer_id = 'CS018205000001'
AND
(
amount >= 1000
OR quantity >= 5
)
;
* postgresql://padawan:***@db:5432/dsdojo_db 5 rows affected.
| sales_ymd | customer_id | product_cd | quantity | amount |
|---|---|---|---|---|
| 20180911 | CS018205000001 | P071401012 | 1 | 2200 |
| 20180414 | CS018205000001 | P060104007 | 6 | 600 |
| 20170614 | CS018205000001 | P050206001 | 5 | 990 |
| 20190226 | CS018205000001 | P071401020 | 1 | 2200 |
| 20180911 | CS018205000001 | P071401005 | 1 | 1100 |
S-007: レシート明細データ(receipt)から売上日(sales_ymd)、顧客ID(customer_id)、商品コード(product_cd)、売上金額(amount)の順に列を指定し、以下の全ての条件を満たすデータを抽出せよ。
- 顧客ID(customer_id)が"CS018205000001"
- 売上金額(amount)が1,000以上2,000以下
%%sql
SELECT
sales_ymd,
customer_id,
product_cd,
amount
FROM
receipt
WHERE
customer_id = 'CS018205000001'
AND amount BETWEEN 1000 AND 2000
;
* postgresql://padawan:***@db:5432/dsdojo_db 1 rows affected.
| sales_ymd | customer_id | product_cd | amount |
|---|---|---|---|
| 20180911 | CS018205000001 | P071401005 | 1100 |
S-008: レシート明細データ(receipt)から売上日(sales_ymd)、顧客ID(customer_id)、商品コード(product_cd)、売上金額(amount)の順に列を指定し、以下の全ての条件を満たすデータを抽出せよ。
- 顧客ID(customer_id)が"CS018205000001"
- 商品コード(product_cd)が"P071401019"以外
%%sql
SELECT
sales_ymd,
customer_id,
product_cd, amount
FROM
receipt
WHERE
customer_id = 'CS018205000001'
AND product_cd != 'P071401019'
;
* postgresql://padawan:***@db:5432/dsdojo_db 12 rows affected.
| sales_ymd | customer_id | product_cd | amount |
|---|---|---|---|
| 20180911 | CS018205000001 | P071401012 | 2200 |
| 20180414 | CS018205000001 | P060104007 | 600 |
| 20170614 | CS018205000001 | P050206001 | 990 |
| 20170614 | CS018205000001 | P060702015 | 108 |
| 20190216 | CS018205000001 | P071005024 | 102 |
| 20180414 | CS018205000001 | P071101002 | 278 |
| 20190226 | CS018205000001 | P070902035 | 168 |
| 20190924 | CS018205000001 | P060805001 | 495 |
| 20190226 | CS018205000001 | P071401020 | 2200 |
| 20180911 | CS018205000001 | P071401005 | 1100 |
| 20190216 | CS018205000001 | P040101002 | 218 |
| 20190924 | CS018205000001 | P091503001 | 280 |
S-009: 以下の処理において、出力結果を変えずにORをANDに書き換えよ。
SELECT * FROM store WHERE NOT (prefecture_cd = '13' OR floor_area > 900)
%%sql
SELECT * FROM store WHERE prefecture_cd != '13' AND floor_area <= 900;
* postgresql://padawan:***@db:5432/dsdojo_db 3 rows affected.
| store_cd | store_name | prefecture_cd | prefecture | address | address_kana | tel_no | longitude | latitude | floor_area |
|---|---|---|---|---|---|---|---|---|---|
| S14046 | 北山田店 | 14 | 神奈川県 | 神奈川県横浜市都筑区北山田一丁目 | カナガワケンヨコハマシツヅキクキタヤマタイッチョウメ | 045-123-4049 | 139.5916 | 35.56189 | 831.0 |
| S14011 | 日吉本町店 | 14 | 神奈川県 | 神奈川県横浜市港北区日吉本町四丁目 | カナガワケンヨコハマシコウホククヒヨシホンチョウヨンチョウメ | 045-123-4033 | 139.6316 | 35.54655 | 890.0 |
| S12013 | 習志野店 | 12 | 千葉県 | 千葉県習志野市芝園一丁目 | チバケンナラシノシシバゾノイッチョウメ | 047-123-4002 | 140.022 | 35.66122 | 808.0 |
S-010: 店舗データ(store)から、店舗コード(store_cd)が"S14"で始まるものだけ全項目抽出し、10件表示せよ。
%%sql
SELECT
*
FROM store
WHERE
store_cd LIKE 'S14%'
LIMIT 10
;
* postgresql://padawan:***@db:5432/dsdojo_db 10 rows affected.
| store_cd | store_name | prefecture_cd | prefecture | address | address_kana | tel_no | longitude | latitude | floor_area |
|---|---|---|---|---|---|---|---|---|---|
| S14010 | 菊名店 | 14 | 神奈川県 | 神奈川県横浜市港北区菊名一丁目 | カナガワケンヨコハマシコウホククキクナイッチョウメ | 045-123-4032 | 139.6326 | 35.50049 | 1732.0 |
| S14033 | 阿久和店 | 14 | 神奈川県 | 神奈川県横浜市瀬谷区阿久和西一丁目 | カナガワケンヨコハマシセヤクアクワニシイッチョウメ | 045-123-4043 | 139.4961 | 35.45918 | 1495.0 |
| S14036 | 相模原中央店 | 14 | 神奈川県 | 神奈川県相模原市中央二丁目 | カナガワケンサガミハラシチュウオウニチョウメ | 042-123-4045 | 139.3716 | 35.57327 | 1679.0 |
| S14040 | 長津田店 | 14 | 神奈川県 | 神奈川県横浜市緑区長津田みなみ台五丁目 | カナガワケンヨコハマシミドリクナガツタミナミダイゴチョウメ | 045-123-4046 | 139.4994 | 35.52398 | 1548.0 |
| S14050 | 阿久和西店 | 14 | 神奈川県 | 神奈川県横浜市瀬谷区阿久和西一丁目 | カナガワケンヨコハマシセヤクアクワニシイッチョウメ | 045-123-4053 | 139.4961 | 35.45918 | 1830.0 |
| S14028 | 二ツ橋店 | 14 | 神奈川県 | 神奈川県横浜市瀬谷区二ツ橋町 | カナガワケンヨコハマシセヤクフタツバシチョウ | 045-123-4042 | 139.4963 | 35.46304 | 1574.0 |
| S14012 | 本牧和田店 | 14 | 神奈川県 | 神奈川県横浜市中区本牧和田 | カナガワケンヨコハマシナカクホンモクワダ | 045-123-4034 | 139.6582 | 35.42156 | 1341.0 |
| S14046 | 北山田店 | 14 | 神奈川県 | 神奈川県横浜市都筑区北山田一丁目 | カナガワケンヨコハマシツヅキクキタヤマタイッチョウメ | 045-123-4049 | 139.5916 | 35.56189 | 831.0 |
| S14022 | 逗子店 | 14 | 神奈川県 | 神奈川県逗子市逗子一丁目 | カナガワケンズシシズシイッチョウメ | 046-123-4036 | 139.5789 | 35.29642 | 1838.0 |
| S14011 | 日吉本町店 | 14 | 神奈川県 | 神奈川県横浜市港北区日吉本町四丁目 | カナガワケンヨコハマシコウホククヒヨシホンチョウヨンチョウメ | 045-123-4033 | 139.6316 | 35.54655 | 890.0 |
S-011: 顧客データ(customer)から顧客ID(customer_id)の末尾が1のものだけ全項目抽出し、10件表示せよ。
%%sql
SELECT * FROM customer WHERE customer_id LIKE '%1' LIMIT 10;
* postgresql://padawan:***@db:5432/dsdojo_db 10 rows affected.
| customer_id | customer_name | gender_cd | gender | birth_day | age | postal_cd | address | application_store_cd | application_date | status_cd |
|---|---|---|---|---|---|---|---|---|---|---|
| CS037613000071 | 六角 雅彦 | 9 | 不明 | 1952-04-01 | 66 | 136-0076 | 東京都江東区南砂********** | S13037 | 20150414 | 0-00000000-0 |
| CS028811000001 | 堀井 かおり | 1 | 女性 | 1933-03-27 | 86 | 245-0016 | 神奈川県横浜市泉区和泉町********** | S14028 | 20160115 | 0-00000000-0 |
| CS040412000191 | 川井 郁恵 | 1 | 女性 | 1977-01-05 | 42 | 226-0021 | 神奈川県横浜市緑区北八朔町********** | S14040 | 20151101 | 1-20091025-4 |
| CS028314000011 | 小菅 あおい | 1 | 女性 | 1983-11-26 | 35 | 246-0038 | 神奈川県横浜市瀬谷区宮沢********** | S14028 | 20151123 | 1-20080426-5 |
| CS039212000051 | 藤島 恵梨香 | 1 | 女性 | 1997-02-03 | 22 | 166-0001 | 東京都杉並区阿佐谷北********** | S13039 | 20171121 | 1-20100215-4 |
| CS015412000111 | 松居 奈月 | 1 | 女性 | 1972-10-04 | 46 | 136-0071 | 東京都江東区亀戸********** | S13015 | 20150629 | 0-00000000-0 |
| CS004702000041 | 野島 洋 | 0 | 男性 | 1943-08-24 | 75 | 176-0022 | 東京都練馬区向山********** | S13004 | 20170218 | 0-00000000-0 |
| CS041515000001 | 栗田 千夏 | 1 | 女性 | 1967-01-02 | 52 | 206-0001 | 東京都多摩市和田********** | S13041 | 20160422 | E-20100803-F |
| CS029313000221 | 北条 ひかり | 1 | 女性 | 1987-06-19 | 31 | 279-0011 | 千葉県浦安市美浜********** | S12029 | 20180810 | 0-00000000-0 |
| CS034312000071 | 望月 奈央 | 1 | 女性 | 1980-09-20 | 38 | 213-0026 | 神奈川県川崎市高津区久末********** | S14034 | 20160106 | 0-00000000-0 |
S-012: 店舗データ(store)から、住所 (address) に"横浜市"が含まれるものだけ全項目表示せよ。
%%sql
SELECT * FROM store WHERE address LIKE '%横浜市%';
* postgresql://padawan:***@db:5432/dsdojo_db 11 rows affected.
| store_cd | store_name | prefecture_cd | prefecture | address | address_kana | tel_no | longitude | latitude | floor_area |
|---|---|---|---|---|---|---|---|---|---|
| S14010 | 菊名店 | 14 | 神奈川県 | 神奈川県横浜市港北区菊名一丁目 | カナガワケンヨコハマシコウホククキクナイッチョウメ | 045-123-4032 | 139.6326 | 35.50049 | 1732.0 |
| S14033 | 阿久和店 | 14 | 神奈川県 | 神奈川県横浜市瀬谷区阿久和西一丁目 | カナガワケンヨコハマシセヤクアクワニシイッチョウメ | 045-123-4043 | 139.4961 | 35.45918 | 1495.0 |
| S14040 | 長津田店 | 14 | 神奈川県 | 神奈川県横浜市緑区長津田みなみ台五丁目 | カナガワケンヨコハマシミドリクナガツタミナミダイゴチョウメ | 045-123-4046 | 139.4994 | 35.52398 | 1548.0 |
| S14050 | 阿久和西店 | 14 | 神奈川県 | 神奈川県横浜市瀬谷区阿久和西一丁目 | カナガワケンヨコハマシセヤクアクワニシイッチョウメ | 045-123-4053 | 139.4961 | 35.45918 | 1830.0 |
| S14028 | 二ツ橋店 | 14 | 神奈川県 | 神奈川県横浜市瀬谷区二ツ橋町 | カナガワケンヨコハマシセヤクフタツバシチョウ | 045-123-4042 | 139.4963 | 35.46304 | 1574.0 |
| S14012 | 本牧和田店 | 14 | 神奈川県 | 神奈川県横浜市中区本牧和田 | カナガワケンヨコハマシナカクホンモクワダ | 045-123-4034 | 139.6582 | 35.42156 | 1341.0 |
| S14046 | 北山田店 | 14 | 神奈川県 | 神奈川県横浜市都筑区北山田一丁目 | カナガワケンヨコハマシツヅキクキタヤマタイッチョウメ | 045-123-4049 | 139.5916 | 35.56189 | 831.0 |
| S14011 | 日吉本町店 | 14 | 神奈川県 | 神奈川県横浜市港北区日吉本町四丁目 | カナガワケンヨコハマシコウホククヒヨシホンチョウヨンチョウメ | 045-123-4033 | 139.6316 | 35.54655 | 890.0 |
| S14048 | 中川中央店 | 14 | 神奈川県 | 神奈川県横浜市都筑区中川中央二丁目 | カナガワケンヨコハマシツヅキクナカガワチュウオウニチョウメ | 045-123-4051 | 139.5758 | 35.54912 | 1657.0 |
| S14042 | 新山下店 | 14 | 神奈川県 | 神奈川県横浜市中区新山下二丁目 | カナガワケンヨコハマシナカクシンヤマシタニチョウメ | 045-123-4047 | 139.6593 | 35.43894 | 1044.0 |
| S14006 | 葛が谷店 | 14 | 神奈川県 | 神奈川県横浜市都筑区葛が谷 | カナガワケンヨコハマシツヅキククズガヤ | 045-123-4031 | 139.5633 | 35.53573 | 1886.0 |
S-013: 顧客データ(customer)から、ステータスコード(status_cd)の先頭がアルファベットのA〜Fで始まるデータを全項目抽出し、10件表示せよ。
%%sql
SELECT * FROM customer WHERE status_cd ~ '^[A-F]' LIMIT 10;
* postgresql://padawan:***@db:5432/dsdojo_db 10 rows affected.
| customer_id | customer_name | gender_cd | gender | birth_day | age | postal_cd | address | application_store_cd | application_date | status_cd |
|---|---|---|---|---|---|---|---|---|---|---|
| CS031415000172 | 宇多田 貴美子 | 1 | 女性 | 1976-10-04 | 42 | 151-0053 | 東京都渋谷区代々木********** | S13031 | 20150529 | D-20100325-C |
| CS015414000103 | 奥野 陽子 | 1 | 女性 | 1977-08-09 | 41 | 136-0073 | 東京都江東区北砂********** | S13015 | 20150722 | B-20100609-B |
| CS011215000048 | 芦田 沙耶 | 1 | 女性 | 1992-02-01 | 27 | 223-0062 | 神奈川県横浜市港北区日吉本町********** | S14011 | 20150228 | C-20100421-9 |
| CS029415000023 | 梅田 里穂 | 1 | 女性 | 1976-01-17 | 43 | 279-0043 | 千葉県浦安市富士見********** | S12029 | 20150610 | D-20100918-E |
| CS035415000029 | 寺沢 真希 | 9 | 不明 | 1977-09-27 | 41 | 158-0096 | 東京都世田谷区玉川台********** | S13035 | 20141220 | F-20101029-F |
| CS031415000106 | 宇野 由美子 | 1 | 女性 | 1970-02-26 | 49 | 151-0053 | 東京都渋谷区代々木********** | S13031 | 20150201 | F-20100511-E |
| CS029215000025 | 石倉 美帆 | 1 | 女性 | 1993-09-28 | 25 | 279-0022 | 千葉県浦安市今川********** | S12029 | 20150708 | B-20100820-C |
| CS033605000005 | 猪股 雄太 | 0 | 男性 | 1955-12-05 | 63 | 246-0031 | 神奈川県横浜市瀬谷区瀬谷********** | S14033 | 20150425 | F-20100917-E |
| CS033415000229 | 板垣 菜々美 | 1 | 女性 | 1977-11-07 | 41 | 246-0021 | 神奈川県横浜市瀬谷区二ツ橋町********** | S14033 | 20150712 | F-20100326-E |
| CS008415000145 | 黒谷 麻緒 | 1 | 女性 | 1977-06-27 | 41 | 157-0067 | 東京都世田谷区喜多見********** | S13008 | 20150829 | F-20100622-F |
S-014: 顧客データ(customer)から、ステータスコード(status_cd)の末尾が数字の1〜9で終わるデータを全項目抽出し、10件表示せよ。
%%sql
SELECT * FROM customer WHERE status_cd ~ '[1-9]$' LIMIT 10;
* postgresql://padawan:***@db:5432/dsdojo_db 10 rows affected.
| customer_id | customer_name | gender_cd | gender | birth_day | age | postal_cd | address | application_store_cd | application_date | status_cd |
|---|---|---|---|---|---|---|---|---|---|---|
| CS001215000145 | 田崎 美紀 | 1 | 女性 | 1995-03-29 | 24 | 144-0055 | 東京都大田区仲六郷********** | S13001 | 20170605 | 6-20090929-2 |
| CS033513000180 | 安斎 遥 | 1 | 女性 | 1962-07-11 | 56 | 241-0823 | 神奈川県横浜市旭区善部町********** | S14033 | 20150728 | 6-20080506-5 |
| CS011215000048 | 芦田 沙耶 | 1 | 女性 | 1992-02-01 | 27 | 223-0062 | 神奈川県横浜市港北区日吉本町********** | S14011 | 20150228 | C-20100421-9 |
| CS040412000191 | 川井 郁恵 | 1 | 女性 | 1977-01-05 | 42 | 226-0021 | 神奈川県横浜市緑区北八朔町********** | S14040 | 20151101 | 1-20091025-4 |
| CS009315000023 | 皆川 文世 | 1 | 女性 | 1980-04-15 | 38 | 154-0012 | 東京都世田谷区駒沢********** | S13009 | 20150319 | 5-20080322-1 |
| CS015315000033 | 福士 璃奈子 | 1 | 女性 | 1983-03-17 | 36 | 135-0043 | 東京都江東区塩浜********** | S13015 | 20141024 | 4-20080219-3 |
| CS023513000066 | 神戸 そら | 1 | 女性 | 1961-12-17 | 57 | 210-0005 | 神奈川県川崎市川崎区東田町********** | S14023 | 20150915 | 5-20100524-9 |
| CS035513000134 | 市川 美帆 | 1 | 女性 | 1960-03-27 | 59 | 156-0053 | 東京都世田谷区桜********** | S13035 | 20150227 | 8-20100711-9 |
| CS001515000263 | 高松 夏空 | 1 | 女性 | 1962-11-09 | 56 | 144-0051 | 東京都大田区西蒲田********** | S13001 | 20160812 | 1-20100804-1 |
| CS040314000027 | 鶴田 きみまろ | 9 | 不明 | 1986-03-26 | 33 | 226-0027 | 神奈川県横浜市緑区長津田********** | S14040 | 20150122 | 2-20080426-4 |
S-015: 顧客データ(customer)から、ステータスコード(status_cd)の先頭がアルファベットのA〜Fで始まり、末尾が数字の1〜9で終わるデータを全項目抽出し、10件表示せよ。
%%sql
SELECT * FROM customer WHERE status_cd ~ '^[A-F].*[1-9]$' LIMIT 10;
* postgresql://padawan:***@db:5432/dsdojo_db 10 rows affected.
| customer_id | customer_name | gender_cd | gender | birth_day | age | postal_cd | address | application_store_cd | application_date | status_cd |
|---|---|---|---|---|---|---|---|---|---|---|
| CS011215000048 | 芦田 沙耶 | 1 | 女性 | 1992-02-01 | 27 | 223-0062 | 神奈川県横浜市港北区日吉本町********** | S14011 | 20150228 | C-20100421-9 |
| CS022513000105 | 島村 貴美子 | 1 | 女性 | 1962-03-12 | 57 | 249-0002 | 神奈川県逗子市山の根********** | S14022 | 20150320 | A-20091115-7 |
| CS001515000096 | 水野 陽子 | 9 | 不明 | 1960-11-29 | 58 | 144-0053 | 東京都大田区蒲田本町********** | S13001 | 20150614 | A-20100724-7 |
| CS013615000053 | 西脇 季衣 | 1 | 女性 | 1953-10-18 | 65 | 261-0026 | 千葉県千葉市美浜区幕張西********** | S12013 | 20150128 | B-20100329-6 |
| CS020412000161 | 小宮 薫 | 1 | 女性 | 1974-05-21 | 44 | 174-0042 | 東京都板橋区東坂下********** | S13020 | 20150822 | B-20081021-3 |
| CS001215000097 | 竹中 あさみ | 1 | 女性 | 1990-07-25 | 28 | 146-0095 | 東京都大田区多摩川********** | S13001 | 20170315 | A-20100211-2 |
| CS035212000007 | 内村 恵梨香 | 1 | 女性 | 1990-12-04 | 28 | 152-0023 | 東京都目黒区八雲********** | S13035 | 20151013 | B-20101018-6 |
| CS002515000386 | 野田 コウ | 1 | 女性 | 1963-05-30 | 55 | 185-0013 | 東京都国分寺市西恋ケ窪********** | S13002 | 20160410 | C-20100127-8 |
| CS001615000372 | 稲垣 寿々花 | 1 | 女性 | 1956-10-29 | 62 | 144-0035 | 東京都大田区南蒲田********** | S13001 | 20170403 | A-20100104-1 |
| CS032512000121 | 松井 知世 | 1 | 女性 | 1962-09-04 | 56 | 210-0011 | 神奈川県川崎市川崎区富士見********** | S13032 | 20150727 | A-20100103-5 |
S-016: 店舗データ(store)から、電話番号(tel_no)が3桁-3桁-4桁のデータを全項目表示せよ。
%%sql
SELECT * FROM store WHERE tel_no ~ '^[0-9]{3}-[0-9]{3}-[0-9]{4}$';
* postgresql://padawan:***@db:5432/dsdojo_db 34 rows affected.
| store_cd | store_name | prefecture_cd | prefecture | address | address_kana | tel_no | longitude | latitude | floor_area |
|---|---|---|---|---|---|---|---|---|---|
| S12014 | 千草台店 | 12 | 千葉県 | 千葉県千葉市稲毛区千草台一丁目 | チバケンチバシイナゲクチグサダイイッチョウメ | 043-123-4003 | 140.118 | 35.63559 | 1698.0 |
| S13002 | 国分寺店 | 13 | 東京都 | 東京都国分寺市本多二丁目 | トウキョウトコクブンジシホンダニチョウメ | 042-123-4008 | 139.4802 | 35.70566 | 1735.0 |
| S14010 | 菊名店 | 14 | 神奈川県 | 神奈川県横浜市港北区菊名一丁目 | カナガワケンヨコハマシコウホククキクナイッチョウメ | 045-123-4032 | 139.6326 | 35.50049 | 1732.0 |
| S14033 | 阿久和店 | 14 | 神奈川県 | 神奈川県横浜市瀬谷区阿久和西一丁目 | カナガワケンヨコハマシセヤクアクワニシイッチョウメ | 045-123-4043 | 139.4961 | 35.45918 | 1495.0 |
| S14036 | 相模原中央店 | 14 | 神奈川県 | 神奈川県相模原市中央二丁目 | カナガワケンサガミハラシチュウオウニチョウメ | 042-123-4045 | 139.3716 | 35.57327 | 1679.0 |
| S14040 | 長津田店 | 14 | 神奈川県 | 神奈川県横浜市緑区長津田みなみ台五丁目 | カナガワケンヨコハマシミドリクナガツタミナミダイゴチョウメ | 045-123-4046 | 139.4994 | 35.52398 | 1548.0 |
| S14050 | 阿久和西店 | 14 | 神奈川県 | 神奈川県横浜市瀬谷区阿久和西一丁目 | カナガワケンヨコハマシセヤクアクワニシイッチョウメ | 045-123-4053 | 139.4961 | 35.45918 | 1830.0 |
| S13052 | 森野店 | 13 | 東京都 | 東京都町田市森野三丁目 | トウキョウトマチダシモリノサンチョウメ | 042-123-4030 | 139.4383 | 35.55293 | 1087.0 |
| S14028 | 二ツ橋店 | 14 | 神奈川県 | 神奈川県横浜市瀬谷区二ツ橋町 | カナガワケンヨコハマシセヤクフタツバシチョウ | 045-123-4042 | 139.4963 | 35.46304 | 1574.0 |
| S14012 | 本牧和田店 | 14 | 神奈川県 | 神奈川県横浜市中区本牧和田 | カナガワケンヨコハマシナカクホンモクワダ | 045-123-4034 | 139.6582 | 35.42156 | 1341.0 |
| S14046 | 北山田店 | 14 | 神奈川県 | 神奈川県横浜市都筑区北山田一丁目 | カナガワケンヨコハマシツヅキクキタヤマタイッチョウメ | 045-123-4049 | 139.5916 | 35.56189 | 831.0 |
| S14022 | 逗子店 | 14 | 神奈川県 | 神奈川県逗子市逗子一丁目 | カナガワケンズシシズシイッチョウメ | 046-123-4036 | 139.5789 | 35.29642 | 1838.0 |
| S14011 | 日吉本町店 | 14 | 神奈川県 | 神奈川県横浜市港北区日吉本町四丁目 | カナガワケンヨコハマシコウホククヒヨシホンチョウヨンチョウメ | 045-123-4033 | 139.6316 | 35.54655 | 890.0 |
| S13016 | 小金井店 | 13 | 東京都 | 東京都小金井市本町一丁目 | トウキョウトコガネイシホンチョウイッチョウメ | 042-123-4015 | 139.5094 | 35.70018 | 1399.0 |
| S14034 | 川崎野川店 | 14 | 神奈川県 | 神奈川県川崎市宮前区野川 | カナガワケンカワサキシミヤマエクノガワ | 044-123-4044 | 139.5998 | 35.57693 | 1318.0 |
| S14048 | 中川中央店 | 14 | 神奈川県 | 神奈川県横浜市都筑区中川中央二丁目 | カナガワケンヨコハマシツヅキクナカガワチュウオウニチョウメ | 045-123-4051 | 139.5758 | 35.54912 | 1657.0 |
| S12007 | 佐倉店 | 12 | 千葉県 | 千葉県佐倉市上志津 | チバケンサクラシカミシヅ | 043-123-4001 | 140.1452 | 35.71872 | 1895.0 |
| S14026 | 辻堂西海岸店 | 14 | 神奈川県 | 神奈川県藤沢市辻堂西海岸二丁目 | カナガワケンフジサワシツジドウニシカイガンニチョウメ | 046-123-4040 | 139.4466 | 35.32464 | 1732.0 |
| S13041 | 八王子店 | 13 | 東京都 | 東京都八王子市大塚 | トウキョウトハチオウジシオオツカ | 042-123-4026 | 139.4235 | 35.63787 | 810.0 |
| S14049 | 川崎大師店 | 14 | 神奈川県 | 神奈川県川崎市川崎区中瀬三丁目 | カナガワケンカワサキシカワサキクナカゼサンチョウメ | 044-123-4052 | 139.7327 | 35.53759 | 962.0 |
| S14023 | 川崎店 | 14 | 神奈川県 | 神奈川県川崎市川崎区本町二丁目 | カナガワケンカワサキシカワサキクホンチョウニチョウメ | 044-123-4037 | 139.7028 | 35.53599 | 1804.0 |
| S13018 | 清瀬店 | 13 | 東京都 | 東京都清瀬市松山一丁目 | トウキョウトキヨセシマツヤマイッチョウメ | 042-123-4017 | 139.5178 | 35.76885 | 1220.0 |
| S14027 | 南藤沢店 | 14 | 神奈川県 | 神奈川県藤沢市南藤沢 | カナガワケンフジサワシミナミフジサワ | 046-123-4041 | 139.4896 | 35.33762 | 1521.0 |
| S14021 | 伊勢原店 | 14 | 神奈川県 | 神奈川県伊勢原市伊勢原四丁目 | カナガワケンイセハラシイセハラヨンチョウメ | 046-123-4035 | 139.3129 | 35.40169 | 962.0 |
| S14047 | 相模原店 | 14 | 神奈川県 | 神奈川県相模原市千代田六丁目 | カナガワケンサガミハラシチヨダロクチョウメ | 042-123-4050 | 139.3748 | 35.55959 | 1047.0 |
| S12013 | 習志野店 | 12 | 千葉県 | 千葉県習志野市芝園一丁目 | チバケンナラシノシシバゾノイッチョウメ | 047-123-4002 | 140.022 | 35.66122 | 808.0 |
| S14042 | 新山下店 | 14 | 神奈川県 | 神奈川県横浜市中区新山下二丁目 | カナガワケンヨコハマシナカクシンヤマシタニチョウメ | 045-123-4047 | 139.6593 | 35.43894 | 1044.0 |
| S12030 | 八幡店 | 12 | 千葉県 | 千葉県市川市八幡三丁目 | チバケンイチカワシヤワタサンチョウメ | 047-123-4005 | 139.924 | 35.72318 | 1162.0 |
| S14025 | 大和店 | 14 | 神奈川県 | 神奈川県大和市下和田 | カナガワケンヤマトシシモワダ | 046-123-4039 | 139.468 | 35.43414 | 1011.0 |
| S14045 | 厚木店 | 14 | 神奈川県 | 神奈川県厚木市中町二丁目 | カナガワケンアツギシナカチョウニチョウメ | 046-123-4048 | 139.3651 | 35.44182 | 980.0 |
| S12029 | 東野店 | 12 | 千葉県 | 千葉県浦安市東野一丁目 | チバケンウラヤスシヒガシノイッチョウメ | 047-123-4004 | 139.8968 | 35.65086 | 1101.0 |
| S12053 | 高洲店 | 12 | 千葉県 | 千葉県浦安市高洲五丁目 | チバケンウラヤスシタカスゴチョウメ | 047-123-4006 | 139.9176 | 35.63755 | 1555.0 |
| S14024 | 三田店 | 14 | 神奈川県 | 神奈川県川崎市多摩区三田四丁目 | カナガワケンカワサキシタマクミタヨンチョウメ | 044-123-4038 | 139.5424 | 35.6077 | 972.0 |
| S14006 | 葛が谷店 | 14 | 神奈川県 | 神奈川県横浜市都筑区葛が谷 | カナガワケンヨコハマシツヅキククズガヤ | 045-123-4031 | 139.5633 | 35.53573 | 1886.0 |
S-017: 顧客データ(customer)を生年月日(birth_day)で高齢順にソートし、先頭から全項目を10件表示せよ。
%%sql
SELECT * FROM customer ORDER BY birth_day LIMIT 10;
* postgresql://padawan:***@db:5432/dsdojo_db 10 rows affected.
| customer_id | customer_name | gender_cd | gender | birth_day | age | postal_cd | address | application_store_cd | application_date | status_cd |
|---|---|---|---|---|---|---|---|---|---|---|
| CS003813000014 | 村山 菜々美 | 1 | 女性 | 1928-11-26 | 90 | 182-0007 | 東京都調布市菊野台********** | S13003 | 20160214 | 0-00000000-0 |
| CS026813000004 | 吉村 朝陽 | 1 | 女性 | 1928-12-14 | 90 | 251-0043 | 神奈川県藤沢市辻堂元町********** | S14026 | 20150723 | 0-00000000-0 |
| CS018811000003 | 熊沢 美里 | 1 | 女性 | 1929-01-07 | 90 | 204-0004 | 東京都清瀬市野塩********** | S13018 | 20150403 | 0-00000000-0 |
| CS027803000004 | 内村 拓郎 | 0 | 男性 | 1929-01-12 | 90 | 251-0031 | 神奈川県藤沢市鵠沼藤が谷********** | S14027 | 20151227 | 0-00000000-0 |
| CS013801000003 | 天野 拓郎 | 0 | 男性 | 1929-01-15 | 90 | 274-0824 | 千葉県船橋市前原東********** | S12013 | 20160120 | 0-00000000-0 |
| CS001814000022 | 鶴田 里穂 | 1 | 女性 | 1929-01-28 | 90 | 144-0045 | 東京都大田区南六郷********** | S13001 | 20161012 | A-20090415-7 |
| CS016815000002 | 山元 美紀 | 1 | 女性 | 1929-02-22 | 90 | 184-0005 | 東京都小金井市桜町********** | S13016 | 20150629 | C-20090923-C |
| CS009815000003 | 中田 里穂 | 1 | 女性 | 1929-04-08 | 89 | 154-0014 | 東京都世田谷区新町********** | S13009 | 20150421 | D-20091021-E |
| CS012813000013 | 宇野 南朋 | 1 | 女性 | 1929-04-09 | 89 | 231-0806 | 神奈川県横浜市中区本牧町********** | S14012 | 20150712 | 0-00000000-0 |
| CS005813000015 | 金谷 恵梨香 | 1 | 女性 | 1929-04-09 | 89 | 165-0032 | 東京都中野区鷺宮********** | S13005 | 20150506 | 0-00000000-0 |
S-018: 顧客データ(customer)を生年月日(birth_day)で若い順にソートし、先頭から全項目を10件表示せよ。
%%sql
SELECT * FROM customer ORDER BY birth_day DESC LIMIT 10;
* postgresql://padawan:***@db:5432/dsdojo_db 10 rows affected.
| customer_id | customer_name | gender_cd | gender | birth_day | age | postal_cd | address | application_store_cd | application_date | status_cd |
|---|---|---|---|---|---|---|---|---|---|---|
| CS035114000004 | 大村 美里 | 1 | 女性 | 2007-11-25 | 11 | 156-0053 | 東京都世田谷区桜********** | S13035 | 20150619 | 6-20091205-6 |
| CS022103000002 | 福山 はじめ | 9 | 不明 | 2007-10-02 | 11 | 249-0006 | 神奈川県逗子市逗子********** | S14022 | 20160909 | 0-00000000-0 |
| CS002113000009 | 柴田 真悠子 | 1 | 女性 | 2007-09-17 | 11 | 184-0014 | 東京都小金井市貫井南町********** | S13002 | 20160304 | 0-00000000-0 |
| CS004115000014 | 松井 京子 | 1 | 女性 | 2007-08-09 | 11 | 165-0031 | 東京都中野区上鷺宮********** | S13004 | 20161120 | 1-20081231-1 |
| CS002114000010 | 山内 遥 | 1 | 女性 | 2007-06-03 | 11 | 184-0015 | 東京都小金井市貫井北町********** | S13002 | 20160920 | 6-20100510-1 |
| CS025115000002 | 小柳 夏希 | 1 | 女性 | 2007-04-18 | 11 | 245-0018 | 神奈川県横浜市泉区上飯田町********** | S14025 | 20160116 | D-20100913-D |
| CS002113000025 | 広末 まなみ | 1 | 女性 | 2007-03-30 | 12 | 184-0015 | 東京都小金井市貫井北町********** | S13002 | 20171030 | 0-00000000-0 |
| CS033112000003 | 長野 美紀 | 1 | 女性 | 2007-03-22 | 12 | 245-0051 | 神奈川県横浜市戸塚区名瀬町********** | S14033 | 20150606 | 0-00000000-0 |
| CS007115000006 | 福岡 瞬 | 1 | 女性 | 2007-03-10 | 12 | 285-0845 | 千葉県佐倉市西志津********** | S12007 | 20151118 | F-20101016-F |
| CS014113000008 | 矢口 莉緒 | 1 | 女性 | 2007-03-05 | 12 | 260-0041 | 千葉県千葉市中央区東千葉********** | S12014 | 20150622 | 3-20091108-6 |
S-019: レシート明細データ(receipt)に対し、1件あたりの売上金額(amount)が高い順にランクを付与し、先頭から10件表示せよ。項目は顧客ID(customer_id)、売上金額(amount)、付与したランクを表示させること。なお、売上金額(amount)が等しい場合は同一順位を付与するものとする。
%%sql
SELECT
customer_id,
amount,
RANK() OVER(ORDER BY amount DESC) AS ranking
FROM receipt
LIMIT 10
;
* postgresql://padawan:***@db:5432/dsdojo_db 10 rows affected.
| customer_id | amount | ranking |
|---|---|---|
| CS011415000006 | 10925 | 1 |
| ZZ000000000000 | 6800 | 2 |
| CS028605000002 | 5780 | 3 |
| ZZ000000000000 | 5480 | 4 |
| ZZ000000000000 | 5480 | 4 |
| CS015515000034 | 5480 | 4 |
| ZZ000000000000 | 5440 | 7 |
| CS021515000089 | 5440 | 7 |
| CS020414000081 | 5280 | 9 |
| ZZ000000000000 | 5280 | 9 |
S-020: レシート明細データ(receipt)に対し、1件あたりの売上金額(amount)が高い順にランクを付与し、先頭から10件表示せよ。項目は顧客ID(customer_id)、売上金額(amount)、付与したランクを表示させること。なお、売上金額(amount)が等しい場合でも別順位を付与すること。
%%sql
SELECT
customer_id,
amount,
ROW_NUMBER() OVER(ORDER BY amount DESC) AS ranking
FROM receipt
LIMIT 10
;
* postgresql://padawan:***@db:5432/dsdojo_db 10 rows affected.
| customer_id | amount | ranking |
|---|---|---|
| CS011415000006 | 10925 | 1 |
| ZZ000000000000 | 6800 | 2 |
| CS028605000002 | 5780 | 3 |
| ZZ000000000000 | 5480 | 4 |
| CS015515000034 | 5480 | 5 |
| ZZ000000000000 | 5480 | 6 |
| ZZ000000000000 | 5440 | 7 |
| CS021515000089 | 5440 | 8 |
| CS001412000160 | 5280 | 9 |
| CS020515000102 | 5280 | 10 |
S-021: レシート明細データ(receipt)に対し、件数をカウントせよ。
%%sql
-- コード例1
SELECT COUNT(1) FROM receipt;
* postgresql://padawan:***@db:5432/dsdojo_db 1 rows affected.
| count |
|---|
| 104681 |
%%sql
-- コード例2(*でもOK)
SELECT COUNT(*) FROM receipt;
* postgresql://padawan:***@db:5432/dsdojo_db 1 rows affected.
| count |
|---|
| 104681 |
S-022: レシート明細データ(receipt)の顧客ID(customer_id)に対し、ユニーク件数をカウントせよ。
%%sql
SELECT
COUNT(DISTINCT customer_id)
FROM receipt
;
* postgresql://padawan:***@db:5432/dsdojo_db 1 rows affected.
| count |
|---|
| 8307 |
S-023: レシート明細データ(receipt)に対し、店舗コード(store_cd)ごとに売上金額(amount)と売上数量(quantity)を合計せよ。
%%sql
SELECT store_cd
, SUM(amount) AS amount
, SUM(quantity) AS quantity
FROM receipt
group by store_cd
;
* postgresql://padawan:***@db:5432/dsdojo_db 52 rows affected.
| store_cd | amount | quantity |
|---|---|---|
| S12007 | 638761 | 2099 |
| S13017 | 748221 | 2376 |
| S13043 | 587895 | 1881 |
| S13052 | 100314 | 250 |
| S13016 | 793773 | 2432 |
| S14027 | 714550 | 2303 |
| S13009 | 808870 | 2486 |
| S14022 | 651328 | 2047 |
| S13019 | 827833 | 2541 |
| S13039 | 611888 | 1981 |
| S14046 | 412646 | 1354 |
| S13003 | 764294 | 2197 |
| S14028 | 786145 | 2458 |
| S14045 | 458484 | 1398 |
| S13002 | 727821 | 2340 |
| S14042 | 534689 | 1935 |
| S13004 | 779373 | 2390 |
| S13038 | 708884 | 2337 |
| S12014 | 725167 | 2358 |
| S14021 | 699511 | 2231 |
| S14006 | 712839 | 2284 |
| S13001 | 811936 | 2347 |
| S14023 | 727630 | 2258 |
| S14025 | 755581 | 2394 |
| S13035 | 715869 | 2219 |
| S14048 | 234276 | 769 |
| S14012 | 720600 | 2412 |
| S14024 | 736323 | 2417 |
| S13041 | 728266 | 2233 |
| S14026 | 824537 | 2503 |
| S14010 | 790361 | 2290 |
| S13015 | 780873 | 2248 |
| S13008 | 809288 | 2491 |
| S14049 | 230808 | 788 |
| S14050 | 167090 | 580 |
| S13031 | 705968 | 2336 |
| S12013 | 787513 | 2425 |
| S13044 | 520764 | 1729 |
| S14033 | 725318 | 2282 |
| S12029 | 794741 | 2555 |
| S13037 | 693087 | 2344 |
| S12030 | 684402 | 2403 |
| S13032 | 790501 | 2491 |
| S14034 | 653681 | 2024 |
| S14040 | 701858 | 2233 |
| S13005 | 629876 | 2004 |
| S14047 | 338329 | 1041 |
| S14011 | 805724 | 2434 |
| S13018 | 790535 | 2562 |
| S13020 | 796383 | 2383 |
| S13051 | 107452 | 354 |
| S14036 | 203694 | 635 |
S-024: レシート明細データ(receipt)に対し、顧客ID(customer_id)ごとに最も新しい売上年月日(sales_ymd)を求め、10件表示せよ。
%%sql
SELECT
customer_id,
MAX(sales_ymd)
FROM receipt
GROUP BY customer_id
LIMIT 10
;
* postgresql://padawan:***@db:5432/dsdojo_db 10 rows affected.
| customer_id | max |
|---|---|
| CS001311000059 | 20180211 |
| CS004614000122 | 20181228 |
| CS003512000043 | 20180106 |
| CS011615000061 | 20190503 |
| CS029212000033 | 20180621 |
| CS007515000119 | 20190511 |
| CS034515000123 | 20190708 |
| CS004315000058 | 20170517 |
| CS026414000014 | 20190720 |
| CS001615000099 | 20170729 |
S-025: レシート明細データ(receipt)に対し、顧客ID(customer_id)ごとに最も古い売上年月日(sales_ymd)を求め、10件表示せよ。
%%sql
SELECT
customer_id,
MIN(sales_ymd)
FROM receipt
GROUP BY customer_id
LIMIT 10
;
* postgresql://padawan:***@db:5432/dsdojo_db 10 rows affected.
| customer_id | min |
|---|---|
| CS001311000059 | 20180211 |
| CS004614000122 | 20181228 |
| CS003512000043 | 20180106 |
| CS011615000061 | 20190503 |
| CS029212000033 | 20170318 |
| CS007515000119 | 20170201 |
| CS034515000123 | 20170527 |
| CS004315000058 | 20170517 |
| CS026414000014 | 20170718 |
| CS001615000099 | 20170729 |
S-026: レシート明細データ(receipt)に対し、顧客ID(customer_id)ごとに最も新しい売上年月日(sales_ymd)と古い売上年月日を求め、両者が異なるデータを10件表示せよ。
%%sql
SELECT
customer_id,
MAX(sales_ymd),
MIN(sales_ymd)
FROM receipt
GROUP BY customer_id
HAVING MAX(sales_ymd) != MIN(sales_ymd)
LIMIT 10
;
* postgresql://padawan:***@db:5432/dsdojo_db 10 rows affected.
| customer_id | max | min |
|---|---|---|
| CS029212000033 | 20180621 | 20170318 |
| CS007515000119 | 20190511 | 20170201 |
| CS034515000123 | 20190708 | 20170527 |
| CS026414000014 | 20190720 | 20170718 |
| CS010515000082 | 20181204 | 20180518 |
| CS019315000045 | 20170920 | 20170423 |
| CS008513000099 | 20190308 | 20170722 |
| CS007615000070 | 20191025 | 20170929 |
| CS025415000155 | 20191026 | 20170314 |
| CS016414000063 | 20190617 | 20170109 |
S-027: レシート明細データ(receipt)に対し、店舗コード(store_cd)ごとに売上金額(amount)の平均を計算し、降順でTOP5を表示せよ。
%%sql
SELECT
store_cd,
AVG(amount) AS avg_amount
FROM receipt
GROUP BY store_cd
ORDER BY avg_amount DESC
LIMIT 5
;
* postgresql://padawan:***@db:5432/dsdojo_db 5 rows affected.
| store_cd | avg_amount |
|---|---|
| S13052 | 402.8674698795180723 |
| S13015 | 351.1119604316546763 |
| S13003 | 350.9155188246097337 |
| S14010 | 348.7912621359223301 |
| S13001 | 348.4703862660944206 |
S-028: レシート明細データ(receipt)に対し、店舗コード(store_cd)ごとに売上金額(amount)の中央値を計算し、降順でTOP5を表示せよ。
%%sql
SELECT
store_cd,
PERCENTILE_CONT(0.5) WITHIN GROUP(ORDER BY amount) AS amount_50per
FROM receipt
GROUP BY store_cd
ORDER BY amount_50per DESC
LIMIT 5
;
* postgresql://padawan:***@db:5432/dsdojo_db 5 rows affected.
| store_cd | amount_50per |
|---|---|
| S13052 | 190.0 |
| S14010 | 188.0 |
| S14050 | 185.0 |
| S13003 | 180.0 |
| S13018 | 180.0 |
S-029: レシート明細データ(receipt)に対し、店舗コード(store_cd)ごとに商品コード(product_cd)の最頻値を求め、10件表示させよ。
%%sql
-- コード例1: window関数や分析関数で最頻値を集計する
WITH product_cnt AS (
SELECT
store_cd,
product_cd,
COUNT(1) AS mode_cnt
FROM receipt
GROUP BY
store_cd,
product_cd
),
product_mode AS (
SELECT
store_cd,
product_cd,
mode_cnt,
RANK() OVER(PARTITION BY store_cd ORDER BY mode_cnt DESC) AS rnk
FROM product_cnt
)
SELECT
store_cd,
product_cd,
mode_cnt
FROM product_mode
WHERE
rnk = 1
ORDER BY
store_cd,
product_cd
LIMIT 10
;
* postgresql://padawan:***@db:5432/dsdojo_db 10 rows affected.
| store_cd | product_cd | mode_cnt |
|---|---|---|
| S12007 | P060303001 | 72 |
| S12013 | P060303001 | 107 |
| S12014 | P060303001 | 65 |
| S12029 | P060303001 | 92 |
| S12030 | P060303001 | 115 |
| S13001 | P060303001 | 67 |
| S13002 | P060303001 | 78 |
| S13003 | P071401001 | 65 |
| S13004 | P060303001 | 88 |
| S13005 | P040503001 | 36 |
%%sql
-- コード例2: MODE()を使う簡易ケース(早いが最頻値が複数の場合は一つだけ選ばれる)
SELECT
store_cd,
MODE() WITHIN GROUP(ORDER BY product_cd)
FROM receipt
GROUP BY store_cd
ORDER BY store_cd
LIMIT 10
;
* postgresql://padawan:***@db:5432/dsdojo_db 10 rows affected.
| store_cd | mode |
|---|---|
| S12007 | P060303001 |
| S12013 | P060303001 |
| S12014 | P060303001 |
| S12029 | P060303001 |
| S12030 | P060303001 |
| S13001 | P060303001 |
| S13002 | P060303001 |
| S13003 | P071401001 |
| S13004 | P060303001 |
| S13005 | P040503001 |
S-030: レシート明細データ(receipt)に対し、店舗コード(store_cd)ごとに売上金額(amount)の分散を計算し、降順で5件表示せよ。
%%sql
SELECT
store_cd,
VAR_POP(amount) AS vars_amount
FROM receipt
GROUP BY store_cd
ORDER BY vars_amount DESC
LIMIT 5
;
* postgresql://padawan:***@db:5432/dsdojo_db 5 rows affected.
| store_cd | vars_amount |
|---|---|
| S13052 | 440088.701311269173 |
| S14011 | 306314.558163888889 |
| S14034 | 296920.081011283873 |
| S13001 | 295431.993329035348 |
| S13015 | 295294.361115940880 |
S-031: レシート明細データ(receipt)に対し、店舗コード(store_cd)ごとに売上金額(amount)の標準偏差を計算し、降順で5件表示せよ。
%%sql
SELECT
store_cd,
STDDEV_POP(amount) as stds_amount
FROM receipt
GROUP BY store_cd
ORDER BY stds_amount DESC
LIMIT 5
;
* postgresql://padawan:***@db:5432/dsdojo_db 5 rows affected.
| store_cd | stds_amount |
|---|---|
| S13052 | 663.391815830787 |
| S14011 | 553.456916267101 |
| S14034 | 544.903735545357 |
| S13001 | 543.536561170484 |
| S13015 | 543.409938366921 |
S-032: レシート明細データ(receipt)の売上金額(amount)について、25%刻みでパーセンタイル値を求めよ。
%%sql
SELECT
PERCENTILE_CONT(0.25) WITHIN GROUP(ORDER BY amount) AS amount_25per,
PERCENTILE_CONT(0.50) WITHIN GROUP(ORDER BY amount) AS amount_50per,
PERCENTILE_CONT(0.75) WITHIN GROUP(ORDER BY amount) AS amount_75per,
PERCENTILE_CONT(1.0) WITHIN GROUP(ORDER BY amount) AS amount_100per
FROM receipt
;
* postgresql://padawan:***@db:5432/dsdojo_db 1 rows affected.
| amount_25per | amount_50per | amount_75per | amount_100per |
|---|---|---|---|
| 102.0 | 170.0 | 288.0 | 10925.0 |
S-033: レシート明細データ(receipt)に対し、店舗コード(store_cd)ごとに売上金額(amount)の平均を計算し、330以上のものを抽出せよ。
%%sql
SELECT
store_cd,
AVG(amount) AS avg_amount
FROM receipt
GROUP BY store_cd
HAVING
AVG(amount) >= 330
;
* postgresql://padawan:***@db:5432/dsdojo_db 13 rows affected.
| store_cd | avg_amount |
|---|---|
| S13052 | 402.8674698795180723 |
| S13019 | 330.2086158755484643 |
| S13003 | 350.9155188246097337 |
| S14045 | 330.0820734341252700 |
| S13004 | 330.9439490445859873 |
| S13001 | 348.4703862660944206 |
| S14026 | 332.3405884723901653 |
| S14010 | 348.7912621359223301 |
| S13015 | 351.1119604316546763 |
| S12013 | 330.1941299790356394 |
| S14047 | 330.0770731707317073 |
| S14011 | 335.7183333333333333 |
| S13020 | 337.8799321170980059 |
S-034: レシート明細データ(receipt)に対し、顧客ID(customer_id)ごとに売上金額(amount)を合計して全顧客の平均を求めよ。ただし、顧客IDが"Z"から始まるものは非会員を表すため、除外して計算すること。
%%sql
WITH customer_amount AS (
SELECT
customer_id,
SUM(amount) AS sum_amount
FROM receipt
WHERE
customer_id NOT LIKE 'Z%'
GROUP BY customer_id
)
SELECT
AVG(sum_amount)
FROM customer_amount
;
* postgresql://padawan:***@db:5432/dsdojo_db 1 rows affected.
| avg |
|---|
| 2547.7422345292559595 |
S-035: レシート明細データ(receipt)に対し、顧客ID(customer_id)ごとに売上金額(amount)を合計して全顧客の平均を求め、平均以上に買い物をしている顧客を抽出し、10件表示せよ。ただし、顧客IDが"Z"から始まるものは非会員を表すため、除外して計算すること。
%%sql
WITH customer_amount AS (
SELECT
customer_id,
SUM(amount) AS sum_amount
FROM receipt
WHERE
customer_id NOT LIKE 'Z%'
GROUP BY customer_id
)
SELECT
customer_id,
sum_amount
FROM customer_amount
WHERE
sum_amount >= (
SELECT
AVG(sum_amount)
FROM customer_amount
)
LIMIT 10
;
* postgresql://padawan:***@db:5432/dsdojo_db 10 rows affected.
| customer_id | sum_amount |
|---|---|
| CS029212000033 | 3604 |
| CS007515000119 | 7157 |
| CS034515000123 | 3699 |
| CS026414000014 | 6671 |
| CS007615000070 | 2975 |
| CS016414000063 | 6207 |
| CS012514000018 | 2562 |
| CS029515000142 | 3420 |
| CS015215000021 | 3090 |
| CS039814000011 | 8031 |
S-036: レシート明細データ(receipt)と店舗データ(store)を内部結合し、レシート明細データの全項目と店舗データの店舗名(store_name)を10件表示せよ。
%%sql
SELECT
r.*,
s.store_name
FROM receipt r
JOIN store s
ON
r.store_cd = s.store_cd
LIMIT 10
;
* postgresql://padawan:***@db:5432/dsdojo_db 10 rows affected.
| sales_ymd | sales_epoch | store_cd | receipt_no | receipt_sub_no | customer_id | product_cd | quantity | amount | store_name |
|---|---|---|---|---|---|---|---|---|---|
| 20181103 | 1541203200 | S14006 | 112 | 1 | CS006214000001 | P070305012 | 1 | 158 | 葛が谷店 |
| 20181118 | 1542499200 | S13008 | 1132 | 2 | CS008415000097 | P070701017 | 1 | 81 | 成城店 |
| 20170712 | 1499817600 | S14028 | 1102 | 1 | CS028414000014 | P060101005 | 1 | 170 | 二ツ橋店 |
| 20190205 | 1549324800 | S14042 | 1132 | 1 | ZZ000000000000 | P050301001 | 1 | 25 | 新山下店 |
| 20180821 | 1534809600 | S14025 | 1102 | 2 | CS025415000050 | P060102007 | 1 | 90 | 大和店 |
| 20190605 | 1559692800 | S13003 | 1112 | 1 | CS003515000195 | P050102002 | 1 | 138 | 狛江店 |
| 20181205 | 1543968000 | S14024 | 1102 | 2 | CS024514000042 | P080101005 | 1 | 30 | 三田店 |
| 20190922 | 1569110400 | S14040 | 1102 | 1 | CS040415000178 | P070501004 | 1 | 128 | 長津田店 |
| 20170504 | 1493856000 | S13020 | 1112 | 2 | ZZ000000000000 | P071302010 | 1 | 770 | 十条仲原店 |
| 20191010 | 1570665600 | S14027 | 1102 | 1 | CS027514000015 | P071101003 | 1 | 680 | 南藤沢店 |
S-037: 商品データ(product)とカテゴリデータ(category)を内部結合し、商品データの全項目とカテゴリデータのカテゴリ小区分名(category_small_name)を10件表示せよ。
%%sql
SELECT
p.*,
c.category_small_name
FROM product p
JOIN category c
ON
p.category_small_cd = c.category_small_cd
LIMIT 10
;
* postgresql://padawan:***@db:5432/dsdojo_db 10 rows affected.
| product_cd | category_major_cd | category_medium_cd | category_small_cd | unit_price | unit_cost | category_small_name |
|---|---|---|---|---|---|---|
| P040101001 | 04 | 0401 | 040101 | 198 | 149 | 弁当類 |
| P040101002 | 04 | 0401 | 040101 | 218 | 164 | 弁当類 |
| P040101003 | 04 | 0401 | 040101 | 230 | 173 | 弁当類 |
| P040101004 | 04 | 0401 | 040101 | 248 | 186 | 弁当類 |
| P040101005 | 04 | 0401 | 040101 | 268 | 201 | 弁当類 |
| P040101006 | 04 | 0401 | 040101 | 298 | 224 | 弁当類 |
| P040101007 | 04 | 0401 | 040101 | 338 | 254 | 弁当類 |
| P040101008 | 04 | 0401 | 040101 | 420 | 315 | 弁当類 |
| P040101009 | 04 | 0401 | 040101 | 498 | 374 | 弁当類 |
| P040101010 | 04 | 0401 | 040101 | 580 | 435 | 弁当類 |
S-038: 顧客データ(customer)とレシート明細データ(receipt)から、顧客ごとの売上金額合計を求め、10件表示せよ。ただし、売上実績がない顧客については売上金額を0として表示させること。また、顧客は性別コード(gender_cd)が女性(1)であるものを対象とし、非会員(顧客IDが"Z"から始まるもの)は除外すること。
%%sql
WITH customer_amount AS (
SELECT
customer_id,
SUM(amount) AS sum_amount
FROM receipt
GROUP BY
customer_id
),
customer_data AS (
SELECT
customer_id
FROM customer
WHERE
gender_cd = '1'
AND customer_id NOT LIKE 'Z%'
)
SELECT
c.customer_id,
COALESCE(a.sum_amount, 0)
FROM customer_data c
LEFT OUTER JOIN customer_amount a
ON
c.customer_id = a.customer_id
LIMIT 10
;
* postgresql://padawan:***@db:5432/dsdojo_db 10 rows affected.
| customer_id | coalesce |
|---|---|
| CS021313000114 | 0 |
| CS031415000172 | 5088 |
| CS028811000001 | 0 |
| CS001215000145 | 875 |
| CS015414000103 | 3122 |
| CS033513000180 | 868 |
| CS035614000014 | 0 |
| CS011215000048 | 3444 |
| CS009413000079 | 0 |
| CS040412000191 | 210 |
S-039: レシート明細データ(receipt)から、売上日数の多い顧客の上位20件を抽出したデータと、売上金額合計の多い顧客の上位20件を抽出したデータをそれぞれ作成し、さらにその2つを完全外部結合せよ。ただし、非会員(顧客IDが"Z"から始まるもの)は除外すること。
%%sql
WITH customer_data AS (
select
customer_id,
sales_ymd,
amount
FROM receipt
WHERE
customer_id NOT LIKE 'Z%'
),
customer_days AS (
select
customer_id,
COUNT(DISTINCT sales_ymd) come_days
FROM customer_data
GROUP BY
customer_id
ORDER BY
come_days DESC
LIMIT 20
),
customer_amount AS (
SELECT
customer_id,
SUM(amount) buy_amount
FROM customer_data
GROUP BY
customer_id
ORDER BY
buy_amount DESC
LIMIT 20
)
SELECT
COALESCE(d.customer_id, a.customer_id) customer_id,
d.come_days,
a.buy_amount
FROM customer_days d
FULL OUTER JOIN customer_amount a
ON
d.customer_id = a.customer_id
;
* postgresql://padawan:***@db:5432/dsdojo_db 34 rows affected.
| customer_id | come_days | buy_amount |
|---|---|---|
| CS040214000008 | 23 | None |
| CS015415000185 | 22 | 20153 |
| CS010214000010 | 22 | 18585 |
| CS028415000007 | 21 | 19127 |
| CS010214000002 | 21 | None |
| CS017415000097 | 20 | 23086 |
| CS016415000141 | 20 | 18372 |
| CS021514000045 | 19 | None |
| CS022515000226 | 19 | None |
| CS031414000051 | 19 | 19202 |
| CS039414000052 | 19 | None |
| CS014214000023 | 19 | None |
| CS021515000172 | 19 | None |
| CS031414000073 | 18 | None |
| CS007515000107 | 18 | None |
| CS014415000077 | 18 | None |
| CS021515000056 | 18 | None |
| CS032415000209 | 18 | None |
| CS021515000211 | 18 | None |
| CS022515000028 | 18 | None |
| CS011415000006 | None | 16094 |
| CS016415000101 | None | 16348 |
| CS030415000034 | None | 15468 |
| CS021515000089 | None | 17580 |
| CS034415000047 | None | 16083 |
| CS006515000023 | None | 18372 |
| CS038415000104 | None | 17847 |
| CS015515000034 | None | 15300 |
| CS032414000072 | None | 16563 |
| CS011414000106 | None | 18338 |
| CS001605000009 | None | 18925 |
| CS009414000059 | None | 15492 |
| CS035414000024 | None | 17615 |
| CS007514000094 | None | 15735 |
S-040: 全ての店舗と全ての商品を組み合わせたデータを作成したい。店舗データ(store)と商品データ(product)を直積し、件数を計算せよ。
%%sql
SELECT
COUNT(1)
FROM store
CROSS JOIN product
;
* postgresql://padawan:***@db:5432/dsdojo_db 1 rows affected.
| count |
|---|
| 531590 |
S-041: レシート明細データ(receipt)の売上金額(amount)を日付(sales_ymd)ごとに集計し、前回売上があった日からの売上金額増減を計算せよ。そして結果を10件表示せよ。
%%sql
WITH sales_amount_by_date AS (
SELECT
sales_ymd,
SUM(amount) AS amount
FROM receipt
GROUP BY
sales_ymd
),
sales_amount_by_date_with_lag as (
SELECT
sales_ymd,
LAG(sales_ymd, 1) OVER(ORDER BY sales_ymd) lag_ymd,
amount,
LAG(amount, 1) OVER(ORDER BY sales_ymd) AS lag_amount
FROM sales_amount_by_date
)
SELECT
sales_ymd,
amount,
lag_ymd,
lag_amount,
amount - lag_amount AS diff_amount
FROM sales_amount_by_date_with_lag
ORDER BY
sales_ymd
LIMIT 10
;
* postgresql://padawan:***@db:5432/dsdojo_db 10 rows affected.
| sales_ymd | amount | lag_ymd | lag_amount | diff_amount |
|---|---|---|---|---|
| 20170101 | 33723 | None | None | None |
| 20170102 | 24165 | 20170101 | 33723 | -9558 |
| 20170103 | 27503 | 20170102 | 24165 | 3338 |
| 20170104 | 36165 | 20170103 | 27503 | 8662 |
| 20170105 | 37830 | 20170104 | 36165 | 1665 |
| 20170106 | 32387 | 20170105 | 37830 | -5443 |
| 20170107 | 23415 | 20170106 | 32387 | -8972 |
| 20170108 | 24737 | 20170107 | 23415 | 1322 |
| 20170109 | 26718 | 20170108 | 24737 | 1981 |
| 20170110 | 20143 | 20170109 | 26718 | -6575 |
S-042: レシート明細データ(receipt)の売上金額(amount)を日付(sales_ymd)ごとに集計し、各日付のデータに対し、前回、前々回、3回前に売上があった日のデータを結合せよ。そして結果を10件表示せよ。
%%sql
-- コード例1:縦持ちケース
WITH sales_amount_by_date AS (
SELECT
sales_ymd,
SUM(amount) AS amount
FROM receipt
GROUP BY
sales_ymd
),
sales_amount_lag_date AS (
SELECT
sales_ymd,
LAG(sales_ymd, 3) OVER (ORDER BY sales_ymd) AS lag_date_3,
amount
FROM sales_amount_by_date
)
SELECT
a.sales_ymd,
a.amount,
b.sales_ymd AS lag_ymd,
b.amount AS lag_amount
FROM sales_amount_lag_date a
JOIN sales_amount_lag_date b
ON
(
a.lag_date_3 IS NULL
OR a.lag_date_3 <= b.sales_ymd
)
AND b.sales_ymd < a.sales_ymd
ORDER BY
sales_ymd,
lag_ymd
LIMIT 10
;
* postgresql://padawan:***@db:5432/dsdojo_db 10 rows affected.
| sales_ymd | amount | lag_ymd | lag_amount |
|---|---|---|---|
| 20170102 | 24165 | 20170101 | 33723 |
| 20170103 | 27503 | 20170101 | 33723 |
| 20170103 | 27503 | 20170102 | 24165 |
| 20170104 | 36165 | 20170101 | 33723 |
| 20170104 | 36165 | 20170102 | 24165 |
| 20170104 | 36165 | 20170103 | 27503 |
| 20170105 | 37830 | 20170102 | 24165 |
| 20170105 | 37830 | 20170103 | 27503 |
| 20170105 | 37830 | 20170104 | 36165 |
| 20170106 | 32387 | 20170103 | 27503 |
%%sql
-- コード例2:横持ちケース
WITH sales_amount_by_date AS (
SELECT
sales_ymd,
SUM(amount) AS amount
FROM receipt
GROUP BY
sales_ymd
),
sales_amount_with_lag AS (
SELECT
sales_ymd,
amount,
LAG(sales_ymd, 1) OVER (ORDER BY sales_ymd) AS lag_ymd_1,
LAG(amount, 1) OVER (ORDER BY sales_ymd) AS lag_amount_1,
LAG(sales_ymd, 2) OVER (ORDER BY sales_ymd) AS lag_ymd_2,
LAG(amount, 2) OVER (ORDER BY sales_ymd) AS lag_amount_2,
LAG(sales_ymd, 3) OVER (ORDER BY sales_ymd) AS lag_ymd_3,
LAG(amount, 3) OVER (ORDER BY sales_ymd) AS lag_amount_3
FROM sales_amount_by_date
)
SELECT
sales_ymd,
amount,
lag_ymd_1,
lag_amount_1,
lag_ymd_2,
lag_amount_2,
lag_ymd_3,
lag_amount_3
FROM sales_amount_with_lag
WHERE
lag_ymd_3 IS NOT NULL
ORDER BY
sales_ymd
LIMIT 10
;
* postgresql://padawan:***@db:5432/dsdojo_db 10 rows affected.
| sales_ymd | amount | lag_ymd_1 | lag_amount_1 | lag_ymd_2 | lag_amount_2 | lag_ymd_3 | lag_amount_3 |
|---|---|---|---|---|---|---|---|
| 20170104 | 36165 | 20170103 | 27503 | 20170102 | 24165 | 20170101 | 33723 |
| 20170105 | 37830 | 20170104 | 36165 | 20170103 | 27503 | 20170102 | 24165 |
| 20170106 | 32387 | 20170105 | 37830 | 20170104 | 36165 | 20170103 | 27503 |
| 20170107 | 23415 | 20170106 | 32387 | 20170105 | 37830 | 20170104 | 36165 |
| 20170108 | 24737 | 20170107 | 23415 | 20170106 | 32387 | 20170105 | 37830 |
| 20170109 | 26718 | 20170108 | 24737 | 20170107 | 23415 | 20170106 | 32387 |
| 20170110 | 20143 | 20170109 | 26718 | 20170108 | 24737 | 20170107 | 23415 |
| 20170111 | 24287 | 20170110 | 20143 | 20170109 | 26718 | 20170108 | 24737 |
| 20170112 | 23526 | 20170111 | 24287 | 20170110 | 20143 | 20170109 | 26718 |
| 20170113 | 28004 | 20170112 | 23526 | 20170111 | 24287 | 20170110 | 20143 |
S-043: レシート明細データ(receipt)と顧客データ(customer)を結合し、性別コード(gender_cd)と年代(ageから計算)ごとに売上金額(amount)を合計した売上サマリデータを作成せよ。性別コードは0が男性、1が女性、9が不明を表すものとする。
ただし、項目構成は年代、女性の売上金額、男性の売上金額、性別不明の売上金額の4項目とすること(縦に年代、横に性別のクロス集計)。また、年代は10歳ごとの階級とすること。
%%sql
DROP TABLE IF EXISTS sales_summary;
CREATE TABLE sales_summary AS
WITH gender_era_amount AS (
SELECT
TRUNC(age / 10) * 10 AS era,
c.gender_cd,
SUM(r.amount) AS amount
FROM customer c
JOIN receipt r
ON
c.customer_id = r.customer_id
GROUP BY
era,
c.gender_cd
)
SELECT
era,
SUM(CASE WHEN gender_cd = '0' THEN amount END) AS male,
SUM(CASE WHEN gender_cd = '1' THEN amount END) AS female,
SUM(CASE WHEN gender_cd = '9' THEN amount END) AS unknown
FROM gender_era_amount
GROUP BY
era
ORDER BY
era
;
SELECT
*
FROM sales_summary
;
* postgresql://padawan:***@db:5432/dsdojo_db Done. 9 rows affected. 9 rows affected.
| era | male | female | unknown |
|---|---|---|---|
| 10.0 | 1591 | 149836 | 4317 |
| 20.0 | 72940 | 1363724 | 44328 |
| 30.0 | 177322 | 693047 | 50441 |
| 40.0 | 19355 | 9320791 | 483512 |
| 50.0 | 54320 | 6685192 | 342923 |
| 60.0 | 272469 | 987741 | 71418 |
| 70.0 | 13435 | 29764 | 2427 |
| 80.0 | 46360 | 262923 | 5111 |
| 90.0 | None | 6260 | None |
S-044: 043で作成した売上サマリデータ(sales_summary)は性別の売上を横持ちさせたものであった。このデータから性別を縦持ちさせ、年代、性別コード、売上金額の3項目に変換せよ。ただし、性別コードは男性を"00"、女性を"01"、不明を"99"とする。
%%sql
-- SQL向きではないため、やや強引に記載する(カテゴリ数が多いときはとても長いSQLとなってしまう点に注意)
SELECT era, '00' AS gender_cd , male AS amount FROM sales_summary
UNION ALL
SELECT era, '01' AS gender_cd, female AS amount FROM sales_summary
UNION ALL
SELECT era, '99' AS gender_cd, unknown AS amount FROM sales_summary
;
* postgresql://padawan:***@db:5432/dsdojo_db 27 rows affected.
| era | gender_cd | amount |
|---|---|---|
| 10.0 | 00 | 1591 |
| 20.0 | 00 | 72940 |
| 30.0 | 00 | 177322 |
| 40.0 | 00 | 19355 |
| 50.0 | 00 | 54320 |
| 60.0 | 00 | 272469 |
| 70.0 | 00 | 13435 |
| 80.0 | 00 | 46360 |
| 90.0 | 00 | None |
| 10.0 | 01 | 149836 |
| 20.0 | 01 | 1363724 |
| 30.0 | 01 | 693047 |
| 40.0 | 01 | 9320791 |
| 50.0 | 01 | 6685192 |
| 60.0 | 01 | 987741 |
| 70.0 | 01 | 29764 |
| 80.0 | 01 | 262923 |
| 90.0 | 01 | 6260 |
| 10.0 | 99 | 4317 |
| 20.0 | 99 | 44328 |
| 30.0 | 99 | 50441 |
| 40.0 | 99 | 483512 |
| 50.0 | 99 | 342923 |
| 60.0 | 99 | 71418 |
| 70.0 | 99 | 2427 |
| 80.0 | 99 | 5111 |
| 90.0 | 99 | None |
S-045: 顧客データ(customer)の生年月日(birth_day)は日付型でデータを保有している。これをYYYYMMDD形式の文字列に変換し、顧客ID(customer_id)とともに10件表示せよ。
%%sql
SELECT
customer_id,
TO_CHAR(birth_day, 'YYYYMMDD') AS birth_day
FROM customer
LIMIT 10
;
* postgresql://padawan:***@db:5432/dsdojo_db 10 rows affected.
| customer_id | birth_day |
|---|---|
| CS021313000114 | 19810429 |
| CS037613000071 | 19520401 |
| CS031415000172 | 19761004 |
| CS028811000001 | 19330327 |
| CS001215000145 | 19950329 |
| CS020401000016 | 19740915 |
| CS015414000103 | 19770809 |
| CS029403000008 | 19730817 |
| CS015804000004 | 19310502 |
| CS033513000180 | 19620711 |
S-046: 顧客データ(customer)の申し込み日(application_date)はYYYYMMDD形式の文字列型でデータを保有している。これを日付型に変換し、顧客ID(customer_id)とともに10件表示せよ。
%%sql
SELECT
customer_id,
TO_DATE(application_date, 'YYYYMMDD') AS application_date
FROM customer
LIMIT 10
;
* postgresql://padawan:***@db:5432/dsdojo_db 10 rows affected.
| customer_id | application_date |
|---|---|
| CS021313000114 | 2015-09-05 |
| CS037613000071 | 2015-04-14 |
| CS031415000172 | 2015-05-29 |
| CS028811000001 | 2016-01-15 |
| CS001215000145 | 2017-06-05 |
| CS020401000016 | 2015-02-25 |
| CS015414000103 | 2015-07-22 |
| CS029403000008 | 2015-05-15 |
| CS015804000004 | 2015-06-07 |
| CS033513000180 | 2015-07-28 |
S-047: レシート明細データ(receipt)の売上日(sales_ymd)はYYYYMMDD形式の数値型でデータを保有している。これを日付型に変換し、レシート番号(receipt_no)、レシートサブ番号(receipt_sub_no)とともに10件表示せよ。
%%sql
SELECT
receipt_no,
receipt_sub_no,
TO_DATE(CAST(sales_ymd AS VARCHAR), 'YYYYMMDD') AS sales_ymd
FROM receipt
LIMIT 10
;
* postgresql://padawan:***@db:5432/dsdojo_db 10 rows affected.
| receipt_no | receipt_sub_no | sales_ymd |
|---|---|---|
| 112 | 1 | 2018-11-03 |
| 1132 | 2 | 2018-11-18 |
| 1102 | 1 | 2017-07-12 |
| 1132 | 1 | 2019-02-05 |
| 1102 | 2 | 2018-08-21 |
| 1112 | 1 | 2019-06-05 |
| 1102 | 2 | 2018-12-05 |
| 1102 | 1 | 2019-09-22 |
| 1112 | 2 | 2017-05-04 |
| 1102 | 1 | 2019-10-10 |
S-048: レシート明細データ(receipt)の売上エポック秒(sales_epoch)は数値型のUNIX秒でデータを保有している。これを日付型に変換し、レシート番号(receipt_no)、レシートサブ番号(receipt_sub_no)とともに10件表示せよ。
%%sql
SELECT
receipt_no,
receipt_sub_no,
CAST(TO_TIMESTAMP(sales_epoch) AS DATE) AS sales_ymd
FROM receipt
LIMIT 10
;
* postgresql://padawan:***@db:5432/dsdojo_db 10 rows affected.
| receipt_no | receipt_sub_no | sales_ymd |
|---|---|---|
| 112 | 1 | 2018-11-03 |
| 1132 | 2 | 2018-11-18 |
| 1102 | 1 | 2017-07-12 |
| 1132 | 1 | 2019-02-05 |
| 1102 | 2 | 2018-08-21 |
| 1112 | 1 | 2019-06-05 |
| 1102 | 2 | 2018-12-05 |
| 1102 | 1 | 2019-09-22 |
| 1112 | 2 | 2017-05-04 |
| 1102 | 1 | 2019-10-10 |
S-049: レシート明細データ(receipt)の売上エポック秒(sales_epoch)を日付型に変換し、「年」だけ取り出してレシート番号(receipt_no)、レシートサブ番号(receipt_sub_no)とともに10件表示せよ。
%%sql
SELECT
receipt_no,
receipt_sub_no,
EXTRACT(YEAR FROM TO_TIMESTAMP(sales_epoch)) AS sales_year
FROM receipt
LIMIT 10
;
* postgresql://padawan:***@db:5432/dsdojo_db 10 rows affected.
| receipt_no | receipt_sub_no | sales_year |
|---|---|---|
| 112 | 1 | 2018 |
| 1132 | 2 | 2018 |
| 1102 | 1 | 2017 |
| 1132 | 1 | 2019 |
| 1102 | 2 | 2018 |
| 1112 | 1 | 2019 |
| 1102 | 2 | 2018 |
| 1102 | 1 | 2019 |
| 1112 | 2 | 2017 |
| 1102 | 1 | 2019 |
S-050: レシート明細データ(receipt)の売上エポック秒(sales_epoch)を日付型に変換し、「月」だけ取り出してレシート番号(receipt_no)、レシートサブ番号(receipt_sub_no)とともに10件表示せよ。なお、「月」は0埋め2桁で取り出すこと。
%%sql
SELECT
receipt_no,
receipt_sub_no,
TO_CHAR(
EXTRACT(MONTH FROM TO_TIMESTAMP(sales_epoch)),
'FM00'
) AS sales_month
FROM receipt
LIMIT 10
;
* postgresql://padawan:***@db:5432/dsdojo_db 10 rows affected.
| receipt_no | receipt_sub_no | sales_month |
|---|---|---|
| 112 | 1 | 11 |
| 1132 | 2 | 11 |
| 1102 | 1 | 07 |
| 1132 | 1 | 02 |
| 1102 | 2 | 08 |
| 1112 | 1 | 06 |
| 1102 | 2 | 12 |
| 1102 | 1 | 09 |
| 1112 | 2 | 05 |
| 1102 | 1 | 10 |
S-051: レシート明細データ(receipt)の売上エポック秒を日付型に変換し、「日」だけ取り出してレシート番号(receipt_no)、レシートサブ番号(receipt_sub_no)とともに10件表示せよ。なお、「日」は0埋め2桁で取り出すこと。
%%sql
SELECT
receipt_no, receipt_sub_no,
TO_CHAR(EXTRACT(DAY FROM TO_TIMESTAMP(sales_epoch)), 'FM00') AS sales_day
FROM receipt LIMIT 10
;
* postgresql://padawan:***@db:5432/dsdojo_db 10 rows affected.
| receipt_no | receipt_sub_no | sales_day |
|---|---|---|
| 112 | 1 | 03 |
| 1132 | 2 | 18 |
| 1102 | 1 | 12 |
| 1132 | 1 | 05 |
| 1102 | 2 | 21 |
| 1112 | 1 | 05 |
| 1102 | 2 | 05 |
| 1102 | 1 | 22 |
| 1112 | 2 | 04 |
| 1102 | 1 | 10 |
S-052: レシート明細データ(receipt)の売上金額(amount)を顧客ID(customer_id)ごとに合計の上、売上金額合計に対して2,000円以下を0、2,000円より大きい金額を1に二値化し、顧客ID、売上金額合計とともに10件表示せよ。ただし、顧客IDが"Z"から始まるのものは非会員を表すため、除外して計算すること。
%%sql
SELECT
customer_id,
SUM(amount) AS sum_amount,
CASE
WHEN SUM(amount) > 2000 THEN 1
ELSE 0
END AS sales_flg
FROM receipt
WHERE customer_id NOT LIKE 'Z%'
GROUP BY customer_id
LIMIT 10
;
* postgresql://padawan:***@db:5432/dsdojo_db 10 rows affected.
| customer_id | sum_amount | sales_flg |
|---|---|---|
| CS001311000059 | 2302 | 1 |
| CS004614000122 | 248 | 0 |
| CS003512000043 | 298 | 0 |
| CS011615000061 | 246 | 0 |
| CS029212000033 | 3604 | 1 |
| CS007515000119 | 7157 | 1 |
| CS034515000123 | 3699 | 1 |
| CS004315000058 | 490 | 0 |
| CS026414000014 | 6671 | 1 |
| CS001615000099 | 768 | 0 |
S-053: 顧客データ(customer)の郵便番号(postal_cd)に対し、東京(先頭3桁が100〜209のもの)を1、それ以外のものを0に二値化せよ。さらにレシート明細データ(receipt)と結合し、全期間において売上実績のある顧客数を、作成した二値ごとにカウントせよ。
%%sql
WITH cust AS (
SELECT
customer_id,
postal_cd,
CASE
WHEN CAST(SUBSTR(postal_cd, 1, 3) AS INTEGER) BETWEEN 100 AND 209 THEN 1
ELSE 0
END AS postal_flg
FROM
customer
),
rect AS(
SELECT DISTINCT
customer_id
FROM
receipt
)
SELECT
c.postal_flg,
COUNT(DISTINCT c.customer_id) AS customer_cnt
FROM
cust c
JOIN
rect r
USING (customer_id)
GROUP BY
c.postal_flg
;
* postgresql://padawan:***@db:5432/dsdojo_db 2 rows affected.
| postal_flg | customer_cnt |
|---|---|
| 0 | 3906 |
| 1 | 4400 |
S-054: 顧客データ(customer)の住所(address)は、埼玉県、千葉県、東京都、神奈川県のいずれかとなっている。都道府県毎にコード値を作成し、顧客ID、住所とともに10件表示せよ。値は埼玉県を11、千葉県を12、東京都を13、神奈川県を14とすること。
%%sql
-- SQL向きではないため、やや強引に記載する(カテゴリ数が多いときはとても長いSQLとなってしまう点に注意)
-- コード例1(固定で切り出す)
SELECT
customer_id,
address,
CASE SUBSTR(address,1, 3)
WHEN '埼玉県' THEN '11'
WHEN '千葉県' THEN '12'
WHEN '東京都' THEN '13'
WHEN '神奈川' THEN '14'
END AS prefecture_cd
FROM
customer
LIMIT 10
;
* postgresql://padawan:***@db:5432/dsdojo_db 10 rows affected.
| customer_id | address | prefecture_cd |
|---|---|---|
| CS021313000114 | 神奈川県伊勢原市粟窪********** | 14 |
| CS037613000071 | 東京都江東区南砂********** | 13 |
| CS031415000172 | 東京都渋谷区代々木********** | 13 |
| CS028811000001 | 神奈川県横浜市泉区和泉町********** | 14 |
| CS001215000145 | 東京都大田区仲六郷********** | 13 |
| CS020401000016 | 東京都板橋区若木********** | 13 |
| CS015414000103 | 東京都江東区北砂********** | 13 |
| CS029403000008 | 千葉県浦安市海楽********** | 12 |
| CS015804000004 | 東京都江東区北砂********** | 13 |
| CS033513000180 | 神奈川県横浜市旭区善部町********** | 14 |
%%sql
-- コード例2(正規表現を使う)
SELECT
customer_id,
address,
CASE SUBSTRING(address, '^.*?[都道府県]')
WHEN '埼玉県' THEN '11'
WHEN '千葉県' THEN '12'
WHEN '東京都' THEN '13'
WHEN '神奈川県' THEN '14'
END AS prefecture_cd
FROM
customer
LIMIT 10
;
* postgresql://padawan:***@db:5432/dsdojo_db 10 rows affected.
| customer_id | address | prefecture_cd |
|---|---|---|
| CS021313000114 | 神奈川県伊勢原市粟窪********** | 14 |
| CS037613000071 | 東京都江東区南砂********** | 13 |
| CS031415000172 | 東京都渋谷区代々木********** | 13 |
| CS028811000001 | 神奈川県横浜市泉区和泉町********** | 14 |
| CS001215000145 | 東京都大田区仲六郷********** | 13 |
| CS020401000016 | 東京都板橋区若木********** | 13 |
| CS015414000103 | 東京都江東区北砂********** | 13 |
| CS029403000008 | 千葉県浦安市海楽********** | 12 |
| CS015804000004 | 東京都江東区北砂********** | 13 |
| CS033513000180 | 神奈川県横浜市旭区善部町********** | 14 |
%%sql
-- コード例3(LIKEを使う)
SELECT
customer_id,
address,
CASE
WHEN address LIKE '埼玉県%' THEN '11'
WHEN address LIKE '千葉県%' THEN '12'
WHEN address LIKE '東京都%' THEN '13'
WHEN address LIKE '神奈川県%' THEN '14'
END AS prefecture_cd
FROM
customer
LIMIT 10
;
* postgresql://padawan:***@db:5432/dsdojo_db 10 rows affected.
| customer_id | address | prefecture_cd |
|---|---|---|
| CS021313000114 | 神奈川県伊勢原市粟窪********** | 14 |
| CS037613000071 | 東京都江東区南砂********** | 13 |
| CS031415000172 | 東京都渋谷区代々木********** | 13 |
| CS028811000001 | 神奈川県横浜市泉区和泉町********** | 14 |
| CS001215000145 | 東京都大田区仲六郷********** | 13 |
| CS020401000016 | 東京都板橋区若木********** | 13 |
| CS015414000103 | 東京都江東区北砂********** | 13 |
| CS029403000008 | 千葉県浦安市海楽********** | 12 |
| CS015804000004 | 東京都江東区北砂********** | 13 |
| CS033513000180 | 神奈川県横浜市旭区善部町********** | 14 |
S-055: レシート明細(receipt)データの売上金額(amount)を顧客ID(customer_id)ごとに合計し、その合計金額の四分位点を求めよ。その上で、顧客ごとの売上金額合計に対して以下の基準でカテゴリ値を作成し、顧客ID、売上金額合計とともに10件表示せよ。カテゴリ値は順に1〜4とする。
- 最小値以上第1四分位未満 ・・・ 1を付与
- 第1四分位以上第2四分位未満 ・・・ 2を付与
- 第2四分位以上第3四分位未満 ・・・ 3を付与
- 第3四分位以上 ・・・ 4を付与
%%sql
WITH sales_amount AS(
SELECT
customer_id,
SUM(amount) AS sum_amount
FROM
receipt
GROUP BY
customer_id
),
sales_pct AS (
SELECT
PERCENTILE_CONT(0.25) WITHIN GROUP(ORDER BY sum_amount) AS pct25,
PERCENTILE_CONT(0.50) WITHIN GROUP(ORDER BY sum_amount) AS pct50,
PERCENTILE_CONT(0.75) WITHIN GROUP(ORDER BY sum_amount) AS pct75
FROM
sales_amount
)
SELECT
a.customer_id,
a.sum_amount,
CASE
WHEN a.sum_amount < pct25 THEN 1
WHEN pct25 <= a.sum_amount AND a.sum_amount < pct50 THEN 2
WHEN pct50 <= a.sum_amount AND a.sum_amount < pct75 THEN 3
WHEN pct75 <= a.sum_amount THEN 4
END AS pct_group
FROM sales_amount a
CROSS JOIN sales_pct p
LIMIT 10
;
* postgresql://padawan:***@db:5432/dsdojo_db 10 rows affected.
| customer_id | sum_amount | pct_group |
|---|---|---|
| CS001311000059 | 2302 | 3 |
| CS004614000122 | 248 | 1 |
| CS003512000043 | 298 | 1 |
| CS011615000061 | 246 | 1 |
| CS029212000033 | 3604 | 3 |
| CS007515000119 | 7157 | 4 |
| CS034515000123 | 3699 | 4 |
| CS004315000058 | 490 | 1 |
| CS026414000014 | 6671 | 4 |
| CS001615000099 | 768 | 2 |
S-056: 顧客データ(customer)の年齢(age)をもとに10歳刻みで年代を算出し、顧客ID(customer_id)、生年月日(birth_day)とともに10件表示せよ。ただし、60歳以上は全て60歳代とすること。年代を表すカテゴリ名は任意とする。
%%sql
SELECT
customer_id,
birth_day,
-- 確認用の項目
-- age,
LEAST(CAST(TRUNC(age / 10) * 10 AS INTEGER), 60) AS era
FROM
customer
GROUP BY
customer_id,
birth_day
-- 確認用の条件
-- HAVING LEAST(CAST(TRUNC(age / 10) * 10 AS INTEGER), 60) >= 60
LIMIT 10
;
* postgresql://padawan:***@db:5432/dsdojo_db 10 rows affected.
| customer_id | birth_day | era |
|---|---|---|
| CS001105000001 | 2000-01-14 | 10 |
| CS001112000009 | 2006-08-24 | 10 |
| CS001112000019 | 2001-01-31 | 10 |
| CS001112000021 | 2001-12-15 | 10 |
| CS001112000023 | 2004-01-26 | 10 |
| CS001112000024 | 2001-01-16 | 10 |
| CS001112000029 | 2005-01-24 | 10 |
| CS001112000030 | 2003-03-02 | 10 |
| CS001113000004 | 2003-02-22 | 10 |
| CS001113000010 | 2005-05-09 | 10 |
S-057: 056の抽出結果と性別コード(gender_cd)により、新たに性別×年代の組み合わせを表すカテゴリデータを作成し、10件表示せよ。組み合わせを表すカテゴリの値は任意とする。
%%sql
-- 性別コード1桁と年代コード2桁を連結した性年代コードを生成する
SELECT
customer_id,
birth_day,
gender_cd || TO_CHAR(LEAST(CAST(TRUNC(age / 10) * 10 AS INTEGER), 60), 'FM00') AS gender_era
FROM
customer
GROUP BY
customer_id,
birth_day
LIMIT 10
;
* postgresql://padawan:***@db:5432/dsdojo_db 10 rows affected.
| customer_id | birth_day | gender_era |
|---|---|---|
| CS001105000001 | 2000-01-14 | 010 |
| CS001112000009 | 2006-08-24 | 110 |
| CS001112000019 | 2001-01-31 | 110 |
| CS001112000021 | 2001-12-15 | 110 |
| CS001112000023 | 2004-01-26 | 110 |
| CS001112000024 | 2001-01-16 | 110 |
| CS001112000029 | 2005-01-24 | 110 |
| CS001112000030 | 2003-03-02 | 110 |
| CS001113000004 | 2003-02-22 | 110 |
| CS001113000010 | 2005-05-09 | 110 |
S-058: 顧客データ(customer)の性別コード(gender_cd)をダミー変数化し、顧客ID(customer_id)とともに10件表示せよ。
%%sql
-- カテゴリ数が多いときはとても長いSQLとなってしまう点に注意
-- カテゴリを一つ減らしたい場合はCASE文をどれか一つ削ればOK
SELECT
customer_id,
CASE WHEN gender_cd = '0' THEN '1' ELSE '0' END AS gender_cd_0,
CASE WHEN gender_cd = '1' THEN '1' ELSE '0' END AS gender_cd_1,
CASE WHEN gender_cd = '9' THEN '1' ELSE '0' END AS gender_cd_9
FROM
customer
LIMIT 10
;
* postgresql://padawan:***@db:5432/dsdojo_db 10 rows affected.
| customer_id | gender_cd_0 | gender_cd_1 | gender_cd_9 |
|---|---|---|---|
| CS021313000114 | 0 | 1 | 0 |
| CS037613000071 | 0 | 0 | 1 |
| CS031415000172 | 0 | 1 | 0 |
| CS028811000001 | 0 | 1 | 0 |
| CS001215000145 | 0 | 1 | 0 |
| CS020401000016 | 1 | 0 | 0 |
| CS015414000103 | 0 | 1 | 0 |
| CS029403000008 | 1 | 0 | 0 |
| CS015804000004 | 1 | 0 | 0 |
| CS033513000180 | 0 | 1 | 0 |
S-059: レシート明細データ(receipt)の売上金額(amount)を顧客ID(customer_id)ごとに合計し、売上金額合計を平均0、標準偏差1に標準化して顧客ID、売上金額合計とともに10件表示せよ。標準化に使用する標準偏差は、分散の平方根、もしくは不偏分散の平方根のどちらでも良いものとする。ただし、顧客IDが"Z"から始まるのものは非会員を表すため、除外して計算すること。
%%sql
-- コード例1(STDDEV_POPで標準化)
WITH sales_amount AS(
SELECT
customer_id,
SUM(amount) AS sum_amount
FROM
receipt
WHERE
customer_id NOT LIKE 'Z%'
GROUP BY
customer_id
),
stats_amount AS (
SELECT
AVG(sum_amount) AS avg_amount,
STDDEV_POP(sum_amount) AS stddev_amount
FROM
sales_amount
)
SELECT
customer_id,
sum_amount,
(sum_amount - avg_amount) / stddev_amount AS std_amount
FROM sales_amount
CROSS JOIN stats_amount
LIMIT 10
;
* postgresql://padawan:***@db:5432/dsdojo_db 10 rows affected.
| customer_id | sum_amount | std_amount |
|---|---|---|
| CS001311000059 | 2302 | -0.09032946448390523062 |
| CS004614000122 | 248 | -0.84533488878695858131 |
| CS003512000043 | 298 | -0.82695598361891930792 |
| CS011615000061 | 246 | -0.84607004499368015224 |
| CS029212000033 | 3604 | 0.38825722609183744835 |
| CS007515000119 | 7157 | 1.6942622273327082 |
| CS034515000123 | 3699 | 0.42317714591111206778 |
| CS004315000058 | 490 | -0.75638098777364849812 |
| CS026414000014 | 6671 | 1.5156192690993665 |
| CS001615000099 | 768 | -0.65419427503935013810 |
%%sql
-- コード例2(STDDEV_SAMPで標準化、コード例2と若干値が変わる)
WITH sales_amount AS(
SELECT
customer_id,
SUM(amount) AS sum_amount
FROM
receipt
WHERE
customer_id NOT LIKE 'Z%'
GROUP BY
customer_id
),
stats_amount AS (
SELECT
AVG(sum_amount) AS avg_amount,
STDDEV_SAMP(sum_amount) AS stddev_amount
FROM
sales_amount
)
SELECT
customer_id,
sum_amount,
(sum_amount - avg_amount) / stddev_amount AS std_amount
FROM sales_amount
CROSS JOIN stats_amount
LIMIT 10
;
* postgresql://padawan:***@db:5432/dsdojo_db 10 rows affected.
| customer_id | sum_amount | std_amount |
|---|---|---|
| CS001311000059 | 2302 | -0.09032402671702291270 |
| CS004614000122 | 248 | -0.84528400025253654164 |
| CS003512000043 | 298 | -0.82690620148098070841 |
| CS011615000061 | 246 | -0.84601911220339877497 |
| CS029212000033 | 3604 | 0.38823385329429098451 |
| CS007515000119 | 7157 | 1.6941602340010485 |
| CS034515000123 | 3699 | 0.42315167096024706764 |
| CS004315000058 | 490 | -0.75633545419820630882 |
| CS026414000014 | 6671 | 1.5155280299415258 |
| CS001615000099 | 768 | -0.65415489302835587608 |
S-060: レシート明細データ(receipt)の売上金額(amount)を顧客ID(customer_id)ごとに合計し、売上金額合計を最小値0、最大値1に正規化して顧客ID、売上金額合計とともに10件表示せよ。ただし、顧客IDが"Z"から始まるのものは非会員を表すため、除外して計算すること。
%%sql
WITH sales_amount AS(
SELECT
customer_id,
SUM(amount) AS sum_amount
FROM
receipt
WHERE
customer_id NOT LIKE 'Z%'
GROUP BY
customer_id
),
stats_amount AS (
SELECT
MAX(sum_amount) AS max_amount,
MIN(sum_amount) AS min_amount
FROM
sales_amount
)
SELECT
customer_id,
sum_amount,
1.0 * (sum_amount - min_amount)
/ (max_amount - min_amount) AS scale_amount
FROM sales_amount
CROSS JOIN stats_amount
LIMIT 10
;
* postgresql://padawan:***@db:5432/dsdojo_db 10 rows affected.
| customer_id | sum_amount | scale_amount |
|---|---|---|
| CS001311000059 | 2302 | 0.09697601668404588113 |
| CS004614000122 | 248 | 0.00773375043448036149 |
| CS003512000043 | 298 | 0.00990615224191866528 |
| CS011615000061 | 246 | 0.00764685436218282934 |
| CS029212000033 | 3604 | 0.15354535974973931178 |
| CS007515000119 | 7157 | 0.30791623218630517901 |
| CS034515000123 | 3699 | 0.15767292318387208898 |
| CS004315000058 | 490 | 0.01824817518248175182 |
| CS026414000014 | 6671 | 0.28680048661800486618 |
| CS001615000099 | 768 | 0.03032672923183872089 |
S-061: レシート明細データ(receipt)の売上金額(amount)を顧客ID(customer_id)ごとに合計し、売上金額合計を常用対数化(底10)して顧客ID、売上金額合計とともに10件表示せよ。ただし、顧客IDが"Z"から始まるのものは非会員を表すため、除外して計算すること。
%%sql
SELECT
customer_id,
sum_amount,
LOG(sum_amount + 0.5) AS log_amount
FROM
(
SELECT
customer_id,
SUM(amount) AS sum_amount
FROM
receipt
WHERE
customer_id NOT LIKE 'Z%'
GROUP BY
customer_id
) AS sum_amount_tbl
LIMIT 10
;
* postgresql://padawan:***@db:5432/dsdojo_db 10 rows affected.
| customer_id | sum_amount | log_amount |
|---|---|---|
| CS001311000059 | 2302 | 3.3621996388688865 |
| CS004614000122 | 248 | 2.3953263930693509 |
| CS003512000043 | 298 | 2.4749443354653879 |
| CS011615000061 | 246 | 2.3918169236132488 |
| CS029212000033 | 3604 | 3.5568450298595813 |
| CS007515000119 | 7157 | 3.8547613566936362 |
| CS034515000123 | 3699 | 3.5681430316577019 |
| CS004315000058 | 490 | 2.6906390117159673 |
| CS026414000014 | 6671 | 3.8242234903608168 |
| CS001615000099 | 768 | 2.8856438718357639 |
S-062: レシート明細データ(receipt)の売上金額(amount)を顧客ID(customer_id)ごとに合計し、売上金額合計を自然対数化(底e)して顧客ID、売上金額合計とともに10件表示せよ。ただし、顧客IDが"Z"から始まるのものは非会員を表すため、除外して計算すること。
%%sql
SELECT
customer_id,
sum_amount,
LN(sum_amount + 0.5) AS log_amount
FROM
(
SELECT
customer_id,
SUM(amount) AS sum_amount
FROM
receipt
WHERE
customer_id NOT LIKE 'Z%'
GROUP BY
customer_id
) AS sum_amount_tbl
LIMIT 10
;
* postgresql://padawan:***@db:5432/dsdojo_db 10 rows affected.
| customer_id | sum_amount | log_amount |
|---|---|---|
| CS001311000059 | 2302 | 7.7417507681294619 |
| CS004614000122 | 248 | 5.5154428455366834 |
| CS003512000043 | 298 | 5.6987699328326568 |
| CS011615000061 | 246 | 5.5073619934827448 |
| CS029212000033 | 3604 | 8.1899383438446333 |
| CS007515000119 | 7157 | 8.8759160369722701 |
| CS034515000123 | 3699 | 8.2159529543656056 |
| CS004315000058 | 490 | 6.1954252790054178 |
| CS026414000014 | 6671 | 8.8056000011824754 |
| CS001615000099 | 768 | 6.6444405629786506 |
S-063: 商品データ(product)の単価(unit_price)と原価(unit_cost)から各商品の利益額を算出し、結果を10件表示せよ。
%%sql
SELECT
product_cd,
unit_price,
unit_cost,
unit_price - unit_cost AS unit_profit
FROM
product
LIMIT 10
;
* postgresql://padawan:***@db:5432/dsdojo_db 10 rows affected.
| product_cd | unit_price | unit_cost | unit_profit |
|---|---|---|---|
| P040101001 | 198 | 149 | 49 |
| P040101002 | 218 | 164 | 54 |
| P040101003 | 230 | 173 | 57 |
| P040101004 | 248 | 186 | 62 |
| P040101005 | 268 | 201 | 67 |
| P040101006 | 298 | 224 | 74 |
| P040101007 | 338 | 254 | 84 |
| P040101008 | 420 | 315 | 105 |
| P040101009 | 498 | 374 | 124 |
| P040101010 | 580 | 435 | 145 |
S-064: 商品データ(product)の単価(unit_price)と原価(unit_cost)から、各商品の利益率の全体平均を算出せよ。ただし、単価と原価には欠損が生じていることに注意せよ。
%%sql
SELECT
AVG((unit_price * 1.0 - unit_cost) / unit_price) AS unit_profit_rate
FROM
product
LIMIT 10
;
* postgresql://padawan:***@db:5432/dsdojo_db 1 rows affected.
| unit_profit_rate |
|---|
| 0.24911389885177001279 |
S-065: 商品データ(product)の各商品について、利益率が30%となる新たな単価を求めよ。ただし、1円未満は切り捨てること。そして結果を10件表示させ、利益率がおよそ30%付近であることを確認せよ。ただし、単価(unit_price)と原価(unit_cost)には欠損が生じていることに注意せよ。
%%sql
WITH new_price_tbl AS (
SELECT
product_cd,
unit_price,
unit_cost,
TRUNC(unit_cost / 0.7) AS new_price
FROM
product
)
SELECT
*,
(new_price - unit_cost) / new_price AS new_profit_rate
FROM
new_price_tbl
LIMIT 10
;
* postgresql://padawan:***@db:5432/dsdojo_db 10 rows affected.
| product_cd | unit_price | unit_cost | new_price | new_profit_rate |
|---|---|---|---|---|
| P040101001 | 198 | 149 | 212 | 0.29716981132075471698 |
| P040101002 | 218 | 164 | 234 | 0.29914529914529914530 |
| P040101003 | 230 | 173 | 247 | 0.29959514170040485830 |
| P040101004 | 248 | 186 | 265 | 0.29811320754716981132 |
| P040101005 | 268 | 201 | 287 | 0.29965156794425087108 |
| P040101006 | 298 | 224 | 320 | 0.30000000000000000000 |
| P040101007 | 338 | 254 | 362 | 0.29834254143646408840 |
| P040101008 | 420 | 315 | 450 | 0.30000000000000000000 |
| P040101009 | 498 | 374 | 534 | 0.29962546816479400749 |
| P040101010 | 580 | 435 | 621 | 0.29951690821256038647 |
S-066: 商品データ(product)の各商品について、利益率が30%となる新たな単価を求めよ。今回は、1円未満を丸めること(四捨五入または偶数への丸めで良い)。そして結果を10件表示させ、利益率がおよそ30%付近であることを確認せよ。ただし、単価(unit_price)と原価(unit_cost)には欠損が生じていることに注意せよ。
%%sql
WITH new_price_tbl AS (
SELECT
product_cd,
unit_price,
unit_cost,
ROUND(unit_cost / 0.7) AS new_price
FROM
product
)
SELECT
*,
(new_price - unit_cost) / new_price AS new_profit_rate
FROM
new_price_tbl
LIMIT 10
;
* postgresql://padawan:***@db:5432/dsdojo_db 10 rows affected.
| product_cd | unit_price | unit_cost | new_price | new_profit_rate |
|---|---|---|---|---|
| P040101001 | 198 | 149 | 213 | 0.30046948356807511737 |
| P040101002 | 218 | 164 | 234 | 0.29914529914529914530 |
| P040101003 | 230 | 173 | 247 | 0.29959514170040485830 |
| P040101004 | 248 | 186 | 266 | 0.30075187969924812030 |
| P040101005 | 268 | 201 | 287 | 0.29965156794425087108 |
| P040101006 | 298 | 224 | 320 | 0.30000000000000000000 |
| P040101007 | 338 | 254 | 363 | 0.30027548209366391185 |
| P040101008 | 420 | 315 | 450 | 0.30000000000000000000 |
| P040101009 | 498 | 374 | 534 | 0.29962546816479400749 |
| P040101010 | 580 | 435 | 621 | 0.29951690821256038647 |
S-067: 商品データ(product)の各商品について、利益率が30%となる新たな単価を求めよ。今回は、1円未満を切り上げること。そして結果を10件表示させ、利益率がおよそ30%付近であることを確認せよ。ただし、単価(unit_price)と原価(unit_cost)には欠損が生じていることに注意せよ。
%%sql
WITH new_price_tbl AS (
SELECT
product_cd,
unit_price,
unit_cost,
CEIL(unit_cost / 0.7) AS new_price
FROM
product
)
SELECT
*,
(new_price - unit_cost) / new_price AS new_profit_rate
FROM
new_price_tbl
LIMIT 10
;
* postgresql://padawan:***@db:5432/dsdojo_db 10 rows affected.
| product_cd | unit_price | unit_cost | new_price | new_profit_rate |
|---|---|---|---|---|
| P040101001 | 198 | 149 | 213 | 0.30046948356807511737 |
| P040101002 | 218 | 164 | 235 | 0.30212765957446808511 |
| P040101003 | 230 | 173 | 248 | 0.30241935483870967742 |
| P040101004 | 248 | 186 | 266 | 0.30075187969924812030 |
| P040101005 | 268 | 201 | 288 | 0.30208333333333333333 |
| P040101006 | 298 | 224 | 320 | 0.30000000000000000000 |
| P040101007 | 338 | 254 | 363 | 0.30027548209366391185 |
| P040101008 | 420 | 315 | 450 | 0.30000000000000000000 |
| P040101009 | 498 | 374 | 535 | 0.30093457943925233645 |
| P040101010 | 580 | 435 | 622 | 0.30064308681672025723 |
S-068: 商品データ(product)の各商品について、消費税率10%の税込み金額を求めよ。1円未満の端数は切り捨てとし、結果を10件表示せよ。ただし、単価(unit_price)には欠損が生じていることに注意せよ。
%%sql
SELECT
product_cd,
unit_price,
TRUNC(unit_price * 1.1) AS tax_price
FROM
product
LIMIT 10
;
* postgresql://padawan:***@db:5432/dsdojo_db 10 rows affected.
| product_cd | unit_price | tax_price |
|---|---|---|
| P040101001 | 198 | 217 |
| P040101002 | 218 | 239 |
| P040101003 | 230 | 253 |
| P040101004 | 248 | 272 |
| P040101005 | 268 | 294 |
| P040101006 | 298 | 327 |
| P040101007 | 338 | 371 |
| P040101008 | 420 | 462 |
| P040101009 | 498 | 547 |
| P040101010 | 580 | 638 |
S-069: レシート明細データ(receipt)と商品データ(product)を結合し、顧客毎に全商品の売上金額合計と、カテゴリ大区分コード(category_major_cd)が"07"(瓶詰缶詰)の売上金額合計を計算の上、両者の比率を求めよ。抽出対象はカテゴリ大区分コード"07"(瓶詰缶詰)の売上実績がある顧客のみとし、結果を10件表示せよ。
%%sql
WITH amount_all AS(
SELECT
customer_id,
SUM(amount) AS sum_all
FROM
receipt
GROUP BY
customer_id
),
amount_07 AS (
SELECT
r.customer_id,
SUM(r.amount) AS sum_07
FROM
receipt r
JOIN
product p
ON
r.product_cd = p.product_cd
WHERE
p.category_major_cd = '07'
GROUP BY
customer_id
)
SELECT
amount_all.customer_id,
sum_all,
sum_07,
sum_07 * 1.0 / sum_all AS sales_rate
FROM
amount_all
JOIN
amount_07
ON
amount_all.customer_id = amount_07.customer_id
LIMIT 10
;
* postgresql://padawan:***@db:5432/dsdojo_db 10 rows affected.
| customer_id | sum_all | sum_07 | sales_rate |
|---|---|---|---|
| CS001311000059 | 2302 | 102 | 0.04430929626411815812 |
| CS011615000061 | 246 | 98 | 0.39837398373983739837 |
| CS029212000033 | 3604 | 3604 | 1.00000000000000000000 |
| CS007515000119 | 7157 | 2832 | 0.39569652088864049183 |
| CS034515000123 | 3699 | 1202 | 0.32495268991619356583 |
| CS026414000014 | 6671 | 3142 | 0.47099385399490331285 |
| CS001615000099 | 768 | 318 | 0.41406250000000000000 |
| CS010515000082 | 1482 | 553 | 0.37314439946018893387 |
| CS019315000045 | 813 | 380 | 0.46740467404674046740 |
| CS008513000099 | 1322 | 210 | 0.15885022692889561271 |
S-070: レシート明細データ(receipt)の売上日(sales_ymd)に対し、顧客データ(customer)の会員申込日(application_date)からの経過日数を計算し、顧客ID(customer_id)、売上日、会員申込日とともに10件表示せよ(sales_ymdは数値、application_dateは文字列でデータを保持している点に注意)。
%%sql
WITH receipt_distinct AS (
SELECT distinct
customer_id,
sales_ymd
FROM
receipt
)
SELECT
c.customer_id,
r.sales_ymd,
c.application_date,
EXTRACT(DAY FROM (TO_TIMESTAMP(CAST(r.sales_ymd AS VARCHAR), 'YYYYMMDD')
- TO_TIMESTAMP(c.application_date, 'YYYYMMDD'))) AS elapsed_days
FROM
receipt_distinct r
JOIN
customer c
ON
r.customer_id = c.customer_id
LIMIT 10
;
* postgresql://padawan:***@db:5432/dsdojo_db 10 rows affected.
| customer_id | sales_ymd | application_date | elapsed_days |
|---|---|---|---|
| CS017515000010 | 20171117 | 20150803 | 837 |
| CS019515000097 | 20190630 | 20141124 | 1679 |
| CS008515000005 | 20170714 | 20150216 | 879 |
| CS026414000097 | 20170809 | 20150430 | 832 |
| CS034514000008 | 20181012 | 20150807 | 1162 |
| CS029415000089 | 20180409 | 20150723 | 991 |
| CS019411000012 | 20190314 | 20141213 | 1552 |
| CS015614000006 | 20190802 | 20150211 | 1633 |
| CS007515000053 | 20170712 | 20150325 | 840 |
| CS024615000041 | 20170729 | 20150918 | 680 |
S-071: レシート明細データ(receipt)の売上日(sales_ymd)に対し、顧客データ(customer)の会員申込日(application_date)からの経過月数を計算し、顧客ID(customer_id)、売上日、会員申込日とともに10件表示せよ(sales_ymdは数値、application_dateは文字列でデータを保持している点に注意)。1ヶ月未満は切り捨てること。
%%sql
WITH receipt_distinct AS (
SELECT DISTINCT
customer_id,
sales_ymd
FROM
receipt
),
time_age_tbl AS(
SELECT
c.customer_id,
r.sales_ymd,
c.application_date,
AGE(TO_TIMESTAMP(CAST(r.sales_ymd AS VARCHAR), 'YYYYMMDD'),
TO_TIMESTAMP(c.application_date, 'YYYYMMDD')) AS time_age
FROM
receipt_distinct r
JOIN
customer c
ON
r.customer_id = c.customer_id
)
SELECT
customer_id,
sales_ymd,
application_date,
EXTRACT(YEAR FROM time_age) * 12
+ EXTRACT(MONTH FROM time_age) AS elapsed_months
FROM
time_age_tbl
LIMIT 10
;
* postgresql://padawan:***@db:5432/dsdojo_db 10 rows affected.
| customer_id | sales_ymd | application_date | elapsed_months |
|---|---|---|---|
| CS017515000010 | 20171117 | 20150803 | 27 |
| CS019515000097 | 20190630 | 20141124 | 55 |
| CS008515000005 | 20170714 | 20150216 | 28 |
| CS026414000097 | 20170809 | 20150430 | 27 |
| CS034514000008 | 20181012 | 20150807 | 38 |
| CS029415000089 | 20180409 | 20150723 | 32 |
| CS019411000012 | 20190314 | 20141213 | 51 |
| CS015614000006 | 20190802 | 20150211 | 53 |
| CS007515000053 | 20170712 | 20150325 | 27 |
| CS024615000041 | 20170729 | 20150918 | 22 |
S-072: レシート明細データ(receipt)の売上日(sales_ymd)に対し、顧客データ(customer)の会員申込日(application_date)からの経過年数を計算し、顧客ID(customer_id)、売上日、会員申込日とともに10件表示せよ(sales_ymdは数値、application_dateは文字列でデータを保持している点に注意)。1年未満は切り捨てること。
%%sql
WITH receipt_distinct AS (
SELECT distinct
customer_id,
sales_ymd
FROM
receipt
)
SELECT
c.customer_id,
r.sales_ymd,
c.application_date,
EXTRACT(YEAR FROM AGE(
TO_TIMESTAMP(CAST(r.sales_ymd AS VARCHAR), 'YYYYMMDD'),
TO_TIMESTAMP(c.application_date, 'YYYYMMDD'))) AS elapsed_years
FROM
receipt_distinct r
JOIN
customer c
ON
r.customer_id = c.customer_id
LIMIT 10
;
* postgresql://padawan:***@db:5432/dsdojo_db 10 rows affected.
| customer_id | sales_ymd | application_date | elapsed_years |
|---|---|---|---|
| CS017515000010 | 20171117 | 20150803 | 2 |
| CS019515000097 | 20190630 | 20141124 | 4 |
| CS008515000005 | 20170714 | 20150216 | 2 |
| CS026414000097 | 20170809 | 20150430 | 2 |
| CS034514000008 | 20181012 | 20150807 | 3 |
| CS029415000089 | 20180409 | 20150723 | 2 |
| CS019411000012 | 20190314 | 20141213 | 4 |
| CS015614000006 | 20190802 | 20150211 | 4 |
| CS007515000053 | 20170712 | 20150325 | 2 |
| CS024615000041 | 20170729 | 20150918 | 1 |
S-073: レシート明細データ(receipt)の売上日(sales_ymd)に対し、顧客データ(customer)の会員申込日(application_date)からのエポック秒による経過時間を計算し、顧客ID(customer_id)、売上日、会員申込日とともに10件表示せよ(なお、sales_ymdは数値、application_dateは文字列でデータを保持している点に注意)。なお、時間情報は保有していないため各日付は0時0分0秒を表すものとする。
%%sql
WITH receipt_distinct AS (
SELECT distinct
customer_id,
sales_ymd
FROM
receipt
)
SELECT
c.customer_id,
r.sales_ymd,
c.application_date,
EXTRACT(EPOCH FROM
TO_TIMESTAMP(CAST(r.sales_ymd AS VARCHAR), 'YYYYMMDD') -
TO_TIMESTAMP(c.application_date, 'YYYYMMDD')
) AS elapsed_epoch
FROM
receipt_distinct r
JOIN
customer c
ON
r.customer_id = c.customer_id
LIMIT 10
;
* postgresql://padawan:***@db:5432/dsdojo_db 10 rows affected.
| customer_id | sales_ymd | application_date | elapsed_epoch |
|---|---|---|---|
| CS017515000010 | 20171117 | 20150803 | 72316800.000000 |
| CS019515000097 | 20190630 | 20141124 | 145065600.000000 |
| CS008515000005 | 20170714 | 20150216 | 75945600.000000 |
| CS026414000097 | 20170809 | 20150430 | 71884800.000000 |
| CS034514000008 | 20181012 | 20150807 | 100396800.000000 |
| CS029415000089 | 20180409 | 20150723 | 85622400.000000 |
| CS019411000012 | 20190314 | 20141213 | 134092800.000000 |
| CS015614000006 | 20190802 | 20150211 | 141091200.000000 |
| CS007515000053 | 20170712 | 20150325 | 72576000.000000 |
| CS024615000041 | 20170729 | 20150918 | 58752000.000000 |
S-074: レシート明細データ(receipt)の売上日(sales_ymd)に対し、当該週の月曜日からの経過日数を計算し、売上日、直前の月曜日付とともに10件表示せよ(sales_ymdは数値でデータを保持している点に注意)。
%%sql
WITH elapsed_days_tbl AS (
SELECT
TO_DATE(CAST(sales_ymd AS VARCHAR), 'YYYYMMDD') AS sales_ymd,
EXTRACT(DOW FROM (
TO_DATE(CAST(sales_ymd AS VARCHAR), 'YYYYMMDD') - 1)) AS elapsed_days
FROM
receipt
)
SELECT
sales_ymd,
elapsed_days,
sales_ymd - CAST(elapsed_days AS INTEGER) AS monday
FROM
elapsed_days_tbl
LIMIT 10
;
* postgresql://padawan:***@db:5432/dsdojo_db 10 rows affected.
| sales_ymd | elapsed_days | monday |
|---|---|---|
| 2018-11-03 | 5 | 2018-10-29 |
| 2018-11-18 | 6 | 2018-11-12 |
| 2017-07-12 | 2 | 2017-07-10 |
| 2019-02-05 | 1 | 2019-02-04 |
| 2018-08-21 | 1 | 2018-08-20 |
| 2019-06-05 | 2 | 2019-06-03 |
| 2018-12-05 | 2 | 2018-12-03 |
| 2019-09-22 | 6 | 2019-09-16 |
| 2017-05-04 | 3 | 2017-05-01 |
| 2019-10-10 | 3 | 2019-10-07 |
S-075: 顧客データ(customer)からランダムに1%のデータを抽出し、先頭から10件表示せよ。
%%sql
-- コード例1(シンプルにやるなら。ただし1.0%前後で件数変動)
SELECT * FROM customer WHERE RANDOM() <= 0.01
LIMIT 10
;
* postgresql://padawan:***@db:5432/dsdojo_db 10 rows affected.
| customer_id | customer_name | gender_cd | gender | birth_day | age | postal_cd | address | application_store_cd | application_date | status_cd |
|---|---|---|---|---|---|---|---|---|---|---|
| CS019415000117 | 宮脇 芽以 | 1 | 女性 | 1974-07-10 | 44 | 173-0036 | 東京都板橋区向原********** | S13019 | 20141114 | C-20100720-D |
| CS040513000111 | 寺西 奈央 | 1 | 女性 | 1966-06-03 | 52 | 226-0027 | 神奈川県横浜市緑区長津田********** | S14040 | 20150728 | 6-20090622-6 |
| CS029402000041 | 浅利 俊二 | 0 | 男性 | 1975-08-15 | 43 | 134-0013 | 東京都江戸川区江戸川********** | S12029 | 20150220 | 0-00000000-0 |
| CS019712000008 | 梅本 ヒカル | 1 | 女性 | 1945-04-14 | 73 | 173-0037 | 東京都板橋区小茂根********** | S13019 | 20150613 | 0-00000000-0 |
| CS015713000077 | 長沢 結衣 | 1 | 女性 | 1947-10-09 | 71 | 136-0075 | 東京都江東区新砂********** | S13015 | 20150308 | 0-00000000-0 |
| CS008515000014 | 野沢 あさみ | 1 | 女性 | 1959-06-09 | 59 | 157-0067 | 東京都世田谷区喜多見********** | S13008 | 20150219 | 9-20091212-B |
| CS031514000047 | 原口 礼子 | 1 | 女性 | 1963-07-26 | 55 | 151-0064 | 東京都渋谷区上原********** | S13031 | 20150927 | 8-20090607-6 |
| CS004313000412 | 春日 瞳 | 1 | 女性 | 1984-07-26 | 34 | 176-0024 | 東京都練馬区中村********** | S13004 | 20170525 | 0-00000000-0 |
| CS035513000155 | 板倉 昌代 | 1 | 女性 | 1960-06-12 | 58 | 157-0075 | 東京都世田谷区砧公園********** | S13035 | 20150625 | 0-00000000-0 |
| CS003512000587 | 大山 沙知絵 | 1 | 女性 | 1959-04-01 | 59 | 214-0014 | 神奈川県川崎市多摩区登戸********** | S13003 | 20170306 | 0-00000000-0 |
%%sql
-- コード例2(丁寧にやるなら。カウントを作って出力件数を固定)
WITH customer_tmp AS(
SELECT
*
,ROW_NUMBER() OVER(ORDER BY RANDOM()) AS row
,COUNT(*) OVER() AS cnt
FROM customer
)
SELECT
customer_id
,customer_name
,gender_cd
,gender
,birth_day
,age
,postal_cd
,address
,application_store_cd
,application_date
,status_cd
FROM customer_tmp
WHERE row <= cnt * 0.01
LIMIT 10
;
* postgresql://padawan:***@db:5432/dsdojo_db 10 rows affected.
| customer_id | customer_name | gender_cd | gender | birth_day | age | postal_cd | address | application_store_cd | application_date | status_cd |
|---|---|---|---|---|---|---|---|---|---|---|
| CS027514000069 | 土屋 さやか | 9 | 不明 | 1967-02-10 | 52 | 251-0033 | 神奈川県藤沢市片瀬山********** | S14027 | 20141213 | A-20101018-B |
| CS031504000012 | 向井 剛基 | 0 | 男性 | 1966-09-19 | 52 | 151-0062 | 東京都渋谷区元代々木町********** | S13031 | 20150310 | 0-00000000-0 |
| CS028403000022 | 新垣 三郎 | 0 | 男性 | 1973-09-12 | 45 | 246-0012 | 神奈川県横浜市瀬谷区東野********** | S14028 | 20150905 | 0-00000000-0 |
| CS001415000103 | 水谷 千夏 | 1 | 女性 | 1976-12-08 | 42 | 144-0051 | 東京都大田区西蒲田********** | S13001 | 20150509 | A-20100925-C |
| CS019313000145 | 早美 由美子 | 1 | 女性 | 1985-02-20 | 34 | 173-0033 | 東京都板橋区大山西町********** | S13019 | 20141226 | 0-00000000-0 |
| CS002412000346 | 荒川 美嘉 | 1 | 女性 | 1973-03-22 | 46 | 187-0045 | 東京都小平市学園西町********** | S13002 | 20160808 | 0-00000000-0 |
| CS003415000271 | 稲垣 遥 | 1 | 女性 | 1975-12-14 | 43 | 201-0001 | 東京都狛江市西野川********** | S13003 | 20160630 | A-20090325-8 |
| CS029502000052 | 岡崎 優一 | 0 | 男性 | 1963-03-28 | 56 | 134-0085 | 東京都江戸川区南葛西********** | S12029 | 20150803 | 0-00000000-0 |
| CS002515000290 | 大山 みあ | 1 | 女性 | 1959-06-05 | 59 | 185-0023 | 東京都国分寺市西元町********** | S13002 | 20160627 | C-20100730-B |
| CS009314000030 | 西川 奈々 | 1 | 女性 | 1983-05-15 | 35 | 158-0091 | 東京都世田谷区中町********** | S13009 | 20150519 | E-20100910-D |
S-076: 顧客データ(customer)から性別コード(gender_cd)の割合に基づきランダムに10%のデータを層化抽出し、性別コードごとに件数を集計せよ。
%%sql
-- コード例1
WITH cusotmer_random AS (
SELECT
customer_id,
gender_cd,
cnt
FROM (
SELECT
gender_cd,
ARRAY_AGG(customer_id ORDER BY RANDOM()) AS customer_r,
COUNT(1) AS cnt
FROM
customer
GROUP BY gender_cd
)sample, UNNEST(customer_r) AS customer_id
),
cusotmer_rownum AS(
SELECT
* ,
ROW_NUMBER() OVER(PARTITION BY gender_cd) AS rn
FROM
cusotmer_random
)
SELECT
gender_cd,
COUNT(1) AS customer_num
FROM
cusotmer_rownum
WHERE
rn <= cnt * 0.1
GROUP BY
gender_cd
;
* postgresql://padawan:***@db:5432/dsdojo_db 3 rows affected.
| gender_cd | customer_num |
|---|---|
| 0 | 298 |
| 1 | 1791 |
| 9 | 107 |
%%sql
-- コード例2
WITH cusotmer_random AS (
SELECT
* ,
ROW_NUMBER() OVER(PARTITION BY gender_cd ORDER BY RANDOM()) AS rn,
COUNT(1) OVER(PARTITION BY gender_cd) cnt
FROM
customer
)
SELECT
gender_cd,
COUNT(1) AS customer_num
FROM
cusotmer_random
WHERE
rn <= cnt * 0.1
GROUP BY
gender_cd
;
* postgresql://padawan:***@db:5432/dsdojo_db 3 rows affected.
| gender_cd | customer_num |
|---|---|
| 9 | 107 |
| 0 | 298 |
| 1 | 1791 |
S-077: レシート明細データ(receipt)の売上金額を顧客単位に合計し、合計した売上金額の外れ値を抽出せよ。なお、外れ値は売上金額合計を対数化したうえで平均と標準偏差を計算し、その平均から3σを超えて離れたものとする(自然対数と常用対数のどちらでも可)。結果は10件表示せよ。
%%sql
WITH sales_amount AS(
SELECT
customer_id,
SUM(amount) AS sum_amount,
LN(SUM(amount) + 0.5) AS log_sum_amount
FROM
receipt
GROUP BY
customer_id
)
SELECT
customer_id,
sum_amount,
log_sum_amount
FROM
sales_amount
CROSS JOIN (
SELECT
AVG(log_sum_amount) AS avg_amount,
STDDEV_POP(log_sum_amount) AS std_amount
FROM sales_amount
) stats_amount
WHERE
ABS(log_sum_amount - avg_amount) / std_amount > 3
LIMIT 10
;
* postgresql://padawan:***@db:5432/dsdojo_db 1 rows affected.
| customer_id | sum_amount | log_sum_amount |
|---|---|---|
| ZZ000000000000 | 12395003 | 16.332804005823312 |
S-078: レシート明細データ(receipt)の売上金額(amount)を顧客単位に合計し、合計した売上金額の外れ値を抽出せよ。ただし、顧客IDが"Z"から始まるのものは非会員を表すため、除外して計算すること。なお、ここでは外れ値を第1四分位と第3四分位の差であるIQRを用いて、「第1四分位数-1.5×IQR」を下回るもの、または「第3四分位数+1.5×IQR」を超えるものとする。結果は10件表示せよ。
%%sql
WITH sales_amount AS(
SELECT
customer_id,
SUM(amount) AS sum_amount
FROM
receipt
WHERE
customer_id NOT LIKE 'Z%'
GROUP BY
customer_id
)
SELECT
customer_id,
sum_amount
FROM
sales_amount
CROSS JOIN (
SELECT
PERCENTILE_CONT(0.25) WITHIN GROUP(ORDER BY sum_amount) AS amount_25per,
PERCENTILE_CONT(0.75) WITHIN GROUP(ORDER BY sum_amount) AS amount_75per
FROM sales_amount
) stats_amount
WHERE
sum_amount < amount_25per - (amount_75per - amount_25per) * 1.5
OR amount_75per + (amount_75per - amount_25per) * 1.5 < sum_amount
LIMIT 10
;
* postgresql://padawan:***@db:5432/dsdojo_db 10 rows affected.
| customer_id | sum_amount |
|---|---|
| CS013415000226 | 8362 |
| CS011415000041 | 9454 |
| CS014514000004 | 8872 |
| CS021514000008 | 12839 |
| CS014515000007 | 9763 |
| CS040415000220 | 10158 |
| CS028415000161 | 8465 |
| CS034515000173 | 10074 |
| CS022515000065 | 12903 |
| CS007514000094 | 15735 |
S-079: 商品データ(product)の各項目に対し、欠損数を確認せよ。
%%sql
SELECT
SUM(
CASE WHEN product_cd IS NULL THEN 1 ELSE 0 END
) AS product_cd,
SUM(
CASE WHEN category_major_cd IS NULL THEN 1 ELSE 0 END
) AS category_major_cd,
SUM(
CASE WHEN category_medium_cd IS NULL THEN 1 ELSE 0 END
) AS category_medium_cd,
SUM(
CASE WHEN category_small_cd IS NULL THEN 1 ELSE 0 END
) AS category_small_cd,
SUM(
CASE WHEN unit_price IS NULL THEN 1 ELSE 0 END
) AS unit_price,
SUM(
CASE WHEN unit_cost IS NULL THEN 1 ELSE 0 END
) AS unit_cost
FROM product LIMIT 10
;
* postgresql://padawan:***@db:5432/dsdojo_db 1 rows affected.
| product_cd | category_major_cd | category_medium_cd | category_small_cd | unit_price | unit_cost |
|---|---|---|---|---|---|
| 0 | 0 | 0 | 0 | 7 | 7 |
S-080: 商品データ(product)のいずれかの項目に欠損が発生しているレコードを全て削除した新たな商品データを作成せよ。なお、削除前後の件数を表示させ、079で確認した件数だけ減少していることも確認すること。
%%sql
DROP TABLE IF EXISTS product_1;
CREATE TABLE product_1 AS (
SELECT * FROM product
WHERE unit_price IS NOT NULL AND unit_cost IS NOT NULL
);
* postgresql://padawan:***@db:5432/dsdojo_db Done. 10023 rows affected.
[]
%%sql
SELECT '削除前', COUNT(1) FROM product;
* postgresql://padawan:***@db:5432/dsdojo_db 1 rows affected.
| ?column? | count |
|---|---|
| 削除前 | 10030 |
%%sql
SELECT '削除後', COUNT(1) FROM product_1;
* postgresql://padawan:***@db:5432/dsdojo_db 1 rows affected.
| ?column? | count |
|---|---|
| 削除後 | 10023 |
S-081: 単価(unit_price)と原価(unit_cost)の欠損値について、それぞれの平均値で補完した新たな商品データを作成せよ。なお、平均値については1円未満を丸めること(四捨五入または偶数への丸めで良い)。補完実施後、各項目について欠損が生じていないことも確認すること。
%%sql
DROP TABLE IF EXISTS product_2;
CREATE TABLE product_2 AS (
SELECT
product_cd,
category_major_cd,
category_medium_cd,
category_small_cd,
COALESCE(unit_price, unit_avg) AS unit_price,
COALESCE(unit_cost, cost_avg) AS unit_cost
FROM
product
CROSS JOIN (
SELECT
ROUND(AVG(unit_price)) AS unit_avg,
ROUND(AVG(unit_cost)) AS cost_avg
FROM
product
) stats_product
);
* postgresql://padawan:***@db:5432/dsdojo_db Done. 10030 rows affected.
[]
%%sql
SELECT
SUM(CASE WHEN unit_price IS NULL THEN 1 ELSE 0 END) AS unit_price,
SUM(CASE WHEN unit_cost IS NULL THEN 1 ELSE 0 END) AS unit_cost
FROM product_2
LIMIT 10
;
* postgresql://padawan:***@db:5432/dsdojo_db 1 rows affected.
| unit_price | unit_cost |
|---|---|
| 0 | 0 |
S-082: 単価(unit_price)と原価(unit_cost)の欠損値について、それぞれの中央値で補完した新たな商品データを作成せよ。なお、中央値については1円未満を丸めること(四捨五入または偶数への丸めで良い)。補完実施後、各項目について欠損が生じていないことも確認すること。
%%sql
DROP TABLE IF EXISTS product_3;
CREATE TABLE product_3 AS (
SELECT
product_cd,
category_major_cd,
category_medium_cd,
category_small_cd,
COALESCE(unit_price, unit_med) AS unit_price,
COALESCE(unit_cost, cost_med) AS unit_cost
FROM
product
CROSS JOIN (
SELECT
ROUND(
PERCENTILE_CONT(0.5) WITHIN GROUP(ORDER BY unit_price)
) AS unit_med,
ROUND(
PERCENTILE_CONT(0.5) WITHIN GROUP(ORDER BY unit_cost)
) AS cost_med
FROM
product
) stats_product
);
* postgresql://padawan:***@db:5432/dsdojo_db Done. 10030 rows affected.
[]
%%sql
SELECT
SUM(CASE WHEN unit_price IS NULL THEN 1 ELSE 0 END) AS unit_price,
SUM(CASE WHEN unit_cost IS NULL THEN 1 ELSE 0 END) AS unit_cost
FROM product_3
LIMIT 10
;
* postgresql://padawan:***@db:5432/dsdojo_db 1 rows affected.
| unit_price | unit_cost |
|---|---|
| 0 | 0 |
S-083: 単価(unit_price)と原価(unit_cost)の欠損値について、各商品のカテゴリ小区分コード(category_small_cd)ごとに算出した中央値で補完した新たな商品データを作成せよ。なお、中央値については1円未満を丸めること(四捨五入または偶数への丸めで良い)。補完実施後、各項目について欠損が生じていないことも確認すること。
%%sql
DROP TABLE IF EXISTS product_4;
CREATE TABLE product_4 AS (
WITH category_median AS(
SELECT
category_small_cd,
ROUND(
PERCENTILE_CONT(0.5) WITHIN GROUP(ORDER BY unit_price)
) AS unit_med,
ROUND(
PERCENTILE_CONT(0.5) WITHIN GROUP(ORDER BY unit_cost)
) AS cost_med
FROM product
GROUP BY category_small_cd
)
SELECT
product_cd,
category_major_cd,
category_medium_cd,
category_small_cd,
COALESCE(unit_price, unit_med) AS unit_price,
COALESCE(unit_cost, cost_med) AS unit_cost
FROM
product
JOIN
category_median
USING(category_small_cd)
);
* postgresql://padawan:***@db:5432/dsdojo_db Done. 10030 rows affected.
[]
%%sql
SELECT
SUM(CASE WHEN unit_price IS NULL THEN 1 ELSE 0 END) AS unit_price,
SUM(CASE WHEN unit_cost IS NULL THEN 1 ELSE 0 END) AS unit_cost
FROM product_4
LIMIT 10
;
* postgresql://padawan:***@db:5432/dsdojo_db 1 rows affected.
| unit_price | unit_cost |
|---|---|
| 0 | 0 |
S-084: 顧客データ(customer)の全顧客に対して全期間の売上金額に占める2019年売上金額の割合を計算し、新たなデータを作成せよ。ただし、売上実績がない場合は0として扱うこと。そして計算した割合が0超のものを抽出し、結果を10件表示せよ。また、作成したデータに欠損が存在しないことを確認せよ。
%%sql
DROP TABLE IF EXISTS sales_rate;
CREATE TABLE sales_rate AS(
WITH sales_amount_2019 AS (
SELECT
customer_id,
SUM(amount) AS sum_amount_2019
FROM
receipt
WHERE
sales_ymd BETWEEN 20190101 AND 20191231
GROUP BY
customer_id
),
sales_amount_all AS (
SELECT
customer_id,
SUM(amount) AS sum_amount_all
FROM
receipt
GROUP BY
customer_id
)
SELECT
a.customer_id,
COALESCE(b.sum_amount_2019, 0) AS sales_amount_2019,
COALESCE(c.sum_amount_all, 0) AS sales_amount_all,
CASE COALESCE(c.sum_amount_all, 0)
WHEN 0 THEN 0
ELSE COALESCE(b.sum_amount_2019, 0) * 1.0 / c.sum_amount_all
END AS sales_rate
FROM
customer a
LEFT JOIN
sales_amount_2019 b
ON a.customer_id = b.customer_id
LEFT JOIN
sales_amount_all c
ON a.customer_id = c.customer_id);
* postgresql://padawan:***@db:5432/dsdojo_db Done. 21971 rows affected.
[]
%%sql
SELECT * FROM sales_rate
WHERE sales_rate > 0
LIMIT 10
;
* postgresql://padawan:***@db:5432/dsdojo_db 10 rows affected.
| customer_id | sales_amount_2019 | sales_amount_all | sales_rate |
|---|---|---|---|
| CS031415000172 | 2971 | 5088 | 0.58392295597484276730 |
| CS015414000103 | 874 | 3122 | 0.27994875080076873799 |
| CS011215000048 | 248 | 3444 | 0.07200929152148664344 |
| CS029415000023 | 3767 | 5167 | 0.72904973872653377201 |
| CS035415000029 | 5823 | 7504 | 0.77598614072494669510 |
| CS023513000066 | 208 | 771 | 0.26977950713359273671 |
| CS035513000134 | 463 | 1565 | 0.29584664536741214058 |
| CS001515000263 | 216 | 216 | 1.00000000000000000000 |
| CS006415000279 | 229 | 229 | 1.00000000000000000000 |
| CS031415000106 | 215 | 7741 | 0.02777418938121689704 |
%%sql
SELECT
SUM(CASE WHEN customer_id IS NULL THEN 1 ELSE 0 END) AS unit_price,
SUM(CASE WHEN sales_amount_2019 IS NULL THEN 1 ELSE 0 END) AS unit_price,
SUM(CASE WHEN sales_amount_all IS NULL THEN 1 ELSE 0 END) AS unit_cost,
SUM(CASE WHEN sales_rate IS NULL THEN 1 ELSE 0 END) AS unit_cost
FROM sales_rate
;
* postgresql://padawan:***@db:5432/dsdojo_db 1 rows affected.
| unit_price | unit_price_1 | unit_cost | unit_cost_1 |
|---|---|---|---|
| 0 | 0 | 0 | 0 |
S-085: 顧客データ(customer)の全顧客に対し、郵便番号(postal_cd)を用いてジオコードデータ(geocode)を紐付け、新たな顧客データを作成せよ。ただし、1つの郵便番号(postal_cd)に複数の経度(longitude)、緯度(latitude)情報が紐づく場合は、経度(longitude)、緯度(latitude)の平均値を算出して使用すること。また、作成結果を確認するために結果を10件表示せよ。
%%sql
DROP TABLE IF EXISTS customer_1;
CREATE TABLE customer_1 AS (
WITH geocode_avg AS(
SELECT
postal_cd,
AVG(longitude) AS m_longitude,
AVG(latitude) AS m_latitude
FROM
geocode
GROUP BY
postal_cd
)
SELECT
*
FROM
customer c
JOIN
geocode_avg g
USING(postal_cd)
);
* postgresql://padawan:***@db:5432/dsdojo_db Done. 21971 rows affected.
[]
%%sql
SELECT * FROM customer_1 LIMIT 10;
* postgresql://padawan:***@db:5432/dsdojo_db 10 rows affected.
| postal_cd | customer_id | customer_name | gender_cd | gender | birth_day | age | address | application_store_cd | application_date | status_cd | m_longitude | m_latitude |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 136-0076 | CS037613000071 | 六角 雅彦 | 9 | 不明 | 1952-04-01 | 66 | 東京都江東区南砂********** | S13037 | 20150414 | 0-00000000-0 | 139.8350200000000000 | 35.6719300000000000 |
| 151-0053 | CS031415000172 | 宇多田 貴美子 | 1 | 女性 | 1976-10-04 | 42 | 東京都渋谷区代々木********** | S13031 | 20150529 | D-20100325-C | 139.6896500000000000 | 35.6737400000000000 |
| 245-0016 | CS028811000001 | 堀井 かおり | 1 | 女性 | 1933-03-27 | 86 | 神奈川県横浜市泉区和泉町********** | S14028 | 20160115 | 0-00000000-0 | 139.4836000000000000 | 35.3912500000000000 |
| 144-0055 | CS001215000145 | 田崎 美紀 | 1 | 女性 | 1995-03-29 | 24 | 東京都大田区仲六郷********** | S13001 | 20170605 | 6-20090929-2 | 139.7077500000000000 | 35.5408400000000000 |
| 136-0073 | CS015414000103 | 奥野 陽子 | 1 | 女性 | 1977-08-09 | 41 | 東京都江東区北砂********** | S13015 | 20150722 | B-20100609-B | 139.8360100000000000 | 35.6781800000000000 |
| 136-0073 | CS015804000004 | 松谷 米蔵 | 0 | 男性 | 1931-05-02 | 87 | 東京都江東区北砂********** | S13015 | 20150607 | 0-00000000-0 | 139.8360100000000000 | 35.6781800000000000 |
| 276-0022 | CS007403000016 | 依田 満 | 0 | 男性 | 1975-08-18 | 43 | 千葉県八千代市上高野********** | S12007 | 20150914 | 0-00000000-0 | 140.1326000000000000 | 35.7326400000000000 |
| 154-0015 | CS035614000014 | 板倉 菜々美 | 1 | 女性 | 1954-07-16 | 64 | 東京都世田谷区桜新町********** | S13035 | 20150804 | 0-00000000-0 | 139.6429700000000000 | 35.6288900000000000 |
| 223-0062 | CS011215000048 | 芦田 沙耶 | 1 | 女性 | 1992-02-01 | 27 | 神奈川県横浜市港北区日吉本町********** | S14011 | 20150228 | C-20100421-9 | 139.6294600000000000 | 35.5537000000000000 |
| 226-0021 | CS040412000191 | 川井 郁恵 | 1 | 女性 | 1977-01-05 | 42 | 神奈川県横浜市緑区北八朔町********** | S14040 | 20151101 | 1-20091025-4 | 139.5396400000000000 | 35.5276300000000000 |
$$ \mbox{緯度(ラジアン)}:\phi \\ \mbox{経度(ラジアン)}:\lambda \\ \mbox{距離}L = 6371 * \arccos(\sin \phi_1 * \sin \phi_2 + \cos \phi_1 * \cos \phi_2 * \cos(\lambda_1 − \lambda_2)) $$S-086: 085で作成した緯度経度つき顧客データに対し、会員申込店舗コード(application_store_cd)をキーに店舗データ(store)と結合せよ。そして申込み店舗の緯度(latitude)・経度情報(longitude)と顧客住所(address)の緯度・経度を用いて申込み店舗と顧客住所の距離(単位:km)を求め、顧客ID(customer_id)、顧客住所(address)、店舗住所(address)とともに表示せよ。計算式は以下の簡易式で良いものとするが、その他精度の高い方式を利用したライブラリを利用してもかまわない。結果は10件表示せよ。
%%sql
SELECT
c.customer_id,
c.address AS customer_address,
s.address AS store_address,
6371 * ACOS(
SIN(RADIANS(c.m_latitude))
* SIN(RADIANS(s.latitude))
+ COS(RADIANS(c.m_latitude))
* COS(RADIANS(s.latitude))
* COS(RADIANS(c.m_longitude) - RADIANS(s.longitude))
) AS distance FROM
customer_1 c
JOIN
store s
ON
c.application_store_cd = s.store_cd
LIMIT 10
;
* postgresql://padawan:***@db:5432/dsdojo_db 10 rows affected.
| customer_id | customer_address | store_address | distance |
|---|---|---|---|
| CS037613000071 | 東京都江東区南砂********** | 東京都江東区南砂一丁目 | 1.4511822099658445 |
| CS031415000172 | 東京都渋谷区代々木********** | 東京都渋谷区初台二丁目 | 0.4117334789298223 |
| CS028811000001 | 神奈川県横浜市泉区和泉町********** | 神奈川県横浜市瀬谷区二ツ橋町 | 8.065196026704987 |
| CS001215000145 | 東京都大田区仲六郷********** | 東京都大田区仲六郷二丁目 | 1.2684209720729687 |
| CS015414000103 | 東京都江東区北砂********** | 東京都江東区南砂二丁目 | 1.449673414532165 |
| CS015804000004 | 東京都江東区北砂********** | 東京都江東区南砂二丁目 | 1.449673414532165 |
| CS007403000016 | 千葉県八千代市上高野********** | 千葉県佐倉市上志津 | 1.9208032538419055 |
| CS035614000014 | 東京都世田谷区桜新町********** | 東京都世田谷区用賀四丁目 | 1.0214681484997588 |
| CS011215000048 | 神奈川県横浜市港北区日吉本町********** | 神奈川県横浜市港北区日吉本町四丁目 | 0.8182767808775093 |
| CS040412000191 | 神奈川県横浜市緑区北八朔町********** | 神奈川県横浜市緑区長津田みなみ台五丁目 | 3.6641233580823287 |
S-087: 顧客データ(customer)では、異なる店舗での申込みなどにより同一顧客が複数登録されている。名前(customer_name)と郵便番号(postal_cd)が同じ顧客は同一顧客とみなして1顧客1レコードとなるように名寄せした名寄顧客データを作成し、顧客データの件数、名寄顧客データの件数、重複数を算出せよ。ただし、同一顧客に対しては売上金額合計が最も高いものを残し、売上金額合計が同一もしくは売上実績がない顧客については顧客ID(customer_id)の番号が小さいものを残すこととする。
%%sql
DROP TABLE IF EXISTS customer_u;
CREATE TABLE customer_u AS (
WITH sales_amount AS(
SELECT
c.customer_id,
c.customer_name,
c.postal_cd,
COALESCE(SUM(r.amount), 0) AS sum_amount
FROM
customer c
LEFT JOIN
receipt r
ON c.customer_id = r.customer_id
GROUP by
c.customer_id, c.customer_name, c.postal_cd
),
sales_ranking AS(
SELECT
*,
ROW_NUMBER() OVER(
PARTITION BY customer_name, postal_cd
ORDER BY sum_amount desc, customer_id ) AS ranking
FROM sales_amount
)
SELECT c.*
FROM
customer c
JOIN
sales_ranking r
ON
c.customer_id = r.customer_id
AND r.ranking = 1
);
* postgresql://padawan:***@db:5432/dsdojo_db Done. 21941 rows affected.
[]
%%sql
SELECT
customer_cnt,
customer_u_cnt,
customer_cnt - customer_u_cnt AS diff
FROM
(SELECT COUNT(1) AS customer_cnt FROM customer) customer
CROSS JOIN (SELECT COUNT(1) AS customer_u_cnt FROM customer_u) customer_u
;
* postgresql://padawan:***@db:5432/dsdojo_db 1 rows affected.
| customer_cnt | customer_u_cnt | diff |
|---|---|---|
| 21971 | 21941 | 30 |
S-088: 087で作成したデータを元に、顧客データに統合名寄IDを付与したデータを作成せよ。ただし、統合名寄IDは以下の仕様で付与するものとする。
- 重複していない顧客:顧客ID(customer_id)を設定
- 重複している顧客:前設問で抽出したレコードの顧客IDを設定
顧客IDのユニーク件数と、統合名寄IDのユニーク件数の差も確認すること。
%%sql
DROP TABLE IF EXISTS customer_n;
CREATE TABLE customer_n AS (
SELECT
c.*,
u.customer_id AS integration_id
FROM
customer c
JOIN
customer_u u
ON c.customer_name = u.customer_name
AND c.postal_cd = u.postal_cd
);
* postgresql://padawan:***@db:5432/dsdojo_db Done. 21971 rows affected.
[]
%%sql
SELECT COUNT(1) AS ID数の差 FROM customer_n
WHERE customer_id != integration_id;
* postgresql://padawan:***@db:5432/dsdojo_db 1 rows affected.
| id数の差 |
|---|
| 30 |
S-089: 売上実績がある顧客を、予測モデル構築のため学習用データとテスト用データに分割したい。それぞれ8:2の割合でランダムにデータを分割せよ。
%%sql
SELECT SETSEED(0.1);
CREATE TEMP TABLE IF NOT EXISTS sales_customer AS (
SELECT
customer_id ,
ROW_NUMBER() OVER(ORDER BY RANDOM()) AS row
FROM
customer
JOIN
receipt
USING(customer_id)
GROUP BY customer_id
HAVING SUM(AMOUNT) > 0
);
DROP TABLE IF EXISTS customer_train;
CREATE TABLE customer_train AS
SELECT
customer.*
FROM
sales_customer
JOIN
customer
USING(customer_id)
WHERE
sales_customer.row <= (SELECT
COUNT(1)
FROM sales_customer) * 0.8
;
DROP TABLE IF EXISTS customer_test;
CREATE TABLE customer_test AS
SELECT
customer.*
FROM
sales_customer
JOIN
customer
USING(customer_id)
EXCEPT
SELECT * FROM customer_train
;
* postgresql://padawan:***@db:5432/dsdojo_db 1 rows affected. 8306 rows affected. Done. 6644 rows affected. Done. 1662 rows affected.
[]
%%sql
SELECT
train_cnt * 1.0 / all_cnt as 学習データ割合,
test_cnt * 1.0 / all_cnt as テストデータ割合
FROM
(SELECT COUNT(1) AS all_cnt FROM sales_customer) all_data
CROSS JOIN
(SELECT COUNT(1) AS train_cnt FROM customer_train) train_data
CROSS JOIN
(SELECT COUNT(1) AS test_cnt FROM customer_test) test_data
;
* postgresql://padawan:***@db:5432/dsdojo_db 1 rows affected.
| 学習データ割合 | テストデータ割合 |
|---|---|
| 0.79990368408379484710 | 0.20009631591620515290 |
S-090: レシート明細データ(receipt)は2017年1月1日〜2019年10月31日までのデータを有している。売上金額(amount)を月次で集計し、学習用に12ヶ月、テスト用に6ヶ月の時系列モデル構築用データを3セット作成せよ。
%%sql
-- SQL向きではないため、やや強引に記載する(分割数が多くなる場合はSQLが長くなるため現実的ではない)
-- また、秒単位のデータなど時系列が細かく、かつ長期間に渡る場合はデータが膨大となるため注意(そのようなケースではループ処理でモデル学習ができる言語が望ましい)
-- 学習データ(0)とテストデータ(1)を区別するフラグを付与する
-- 下準備として年月ごとに売上金額を集計し、連番を付与
CREATE TEMP TABLE IF NOT EXISTS ts_amount AS (
SELECT
SUBSTR(CAST(sales_ymd AS VARCHAR), 1, 6) AS sales_ym,
SUM(amount) AS sum_amount,
ROW_NUMBER() OVER(
ORDER BY SUBSTR(CAST(sales_ymd AS VARCHAR), 1, 6)) AS rn
FROM
receipt
GROUP BY sales_ym
);
-- SQLでは限界があるが、作成データセットの増加に伴いなるべく使いまわしができるものにする
-- WITH句内のLAG関数について、ラグ期間を変えれば使い回せるよう記述
DROP TABLE IF EXISTS series_data_1 ;
CREATE TABLE series_data_1 AS (
WITH lag_amount AS (
SELECT
sales_ym,
sum_amount,
LAG(rn, 0) OVER (ORDER BY rn) AS rn
FROM ts_amount
)
SELECT
sales_ym,
sum_amount,
CASE WHEN rn <= 12 THEN 0 WHEN 12 < rn THEN 1 END as test_flg
FROM lag_amount
WHERE rn BETWEEN 1 AND 18);
DROP TABLE IF EXISTS series_data_2 ;
CREATE TABLE series_data_2 AS (
WITH lag_amount AS (
SELECT
sales_ym,
sum_amount,
LAG(rn, 6) OVER (ORDER BY rn) AS rn
FROM ts_amount
)
SELECT
sales_ym,
sum_amount,
CASE WHEN rn <= 12 THEN 0 WHEN 12 < rn THEN 1 END as test_flg
FROM lag_amount
WHERE rn BETWEEN 1 AND 18);
DROP TABLE IF EXISTS series_data_3 ;
CREATE TABLE series_data_3 AS (
WITH lag_amount AS (
SELECT
sales_ym,
sum_amount,
LAG(rn, 12) OVER (ORDER BY rn) AS rn
FROM ts_amount
)
SELECT
sales_ym,
sum_amount,
CASE WHEN rn <= 12 THEN 0 WHEN 12 < rn THEN 1 END as test_flg
FROM lag_amount
WHERE rn BETWEEN 1 AND 18);
* postgresql://padawan:***@db:5432/dsdojo_db 34 rows affected. Done. 18 rows affected. Done. 18 rows affected. Done. 18 rows affected.
[]
%%sql
-- series_data_2とseries_data_3の表示は割愛
SELECT * FROM series_data_1;
* postgresql://padawan:***@db:5432/dsdojo_db 18 rows affected.
| sales_ym | sum_amount | test_flg |
|---|---|---|
| 201701 | 902056 | 0 |
| 201702 | 764413 | 0 |
| 201703 | 962945 | 0 |
| 201704 | 847566 | 0 |
| 201705 | 884010 | 0 |
| 201706 | 894242 | 0 |
| 201707 | 959205 | 0 |
| 201708 | 954836 | 0 |
| 201709 | 902037 | 0 |
| 201710 | 905739 | 0 |
| 201711 | 932157 | 0 |
| 201712 | 939654 | 0 |
| 201801 | 944509 | 1 |
| 201802 | 864128 | 1 |
| 201803 | 946588 | 1 |
| 201804 | 937099 | 1 |
| 201805 | 1004438 | 1 |
| 201806 | 1012329 | 1 |
S-091: 顧客データ(customer)の各顧客に対し、売上実績がある顧客数と売上実績がない顧客数が1:1となるようにアンダーサンプリングで抽出せよ。
%%sql
SELECT SETSEED(0.1);
CREATE TEMP TABLE IF NOT EXISTS down_sampling AS (
WITH pre_table_1 AS(
SELECT
c.*
,COALESCE(r.sum_amount,0) AS sum_amount
FROM
customer c
LEFT JOIN (
SELECT
customer_id,
SUM(amount) AS sum_amount
FROM
receipt
GROUP BY
customer_id
) r
ON
c.customer_id=r.customer_id
)
,pre_table_2 AS(
SELECT
*
,CASE WHEN sum_amount > 0 THEN 1 ELSE 0 END AS is_buy_flag
,CASE WHEN sum_amount = 0 THEN 1 ELSE 0 END AS is_not_buy_flag
FROM
pre_table_1
)
,pre_table_3 AS(
SELECT
*
,ROW_NUMBER() OVER(PARTITION BY is_buy_flag ORDER BY RANDOM())
FROM
pre_table_2
CROSS JOIN
(SELECT SUM(is_buy_flag) AS buying FROM pre_table_2) AS t1
CROSS JOIN
(SELECT SUM(is_not_buy_flag) AS not_buying FROM pre_table_2) AS t2
)
SELECT
*
FROM
pre_table_3
WHERE
row_number <= buying
AND row_number <= not_buying
);
* postgresql://padawan:***@db:5432/dsdojo_db 1 rows affected. 16612 rows affected.
[]
%%sql
SELECT is_buy_flag, COUNT(1) FROM down_sampling GROUP BY is_buy_flag;
* postgresql://padawan:***@db:5432/dsdojo_db 2 rows affected.
| is_buy_flag | count |
|---|---|
| 0 | 8306 |
| 1 | 8306 |
S-092: 顧客データ(customer)の性別について、第三正規形へと正規化せよ。
%%sql
DROP TABLE IF EXISTS customer_std;
CREATE TABLE customer_std AS (
SELECT
customer_id,
customer_name,
gender_cd,
birth_day,
age,
postal_cd,
application_store_cd,
application_date,
status_cd
FROM
customer
);
DROP TABLE IF EXISTS gender_std;
CREATE TABLE gender_std AS (
SELECT distinct
gender_cd, gender
FROM
customer
);
* postgresql://padawan:***@db:5432/dsdojo_db Done. 21971 rows affected. Done. 3 rows affected.
[]
%%sql
-- データの内容確認
SELECT * FROM customer_std LIMIT 3;
* postgresql://padawan:***@db:5432/dsdojo_db 3 rows affected.
| customer_id | customer_name | gender_cd | birth_day | age | postal_cd | application_store_cd | application_date | status_cd |
|---|---|---|---|---|---|---|---|---|
| CS021313000114 | 大野 あや子 | 1 | 1981-04-29 | 37 | 259-1113 | S14021 | 20150905 | 0-00000000-0 |
| CS037613000071 | 六角 雅彦 | 9 | 1952-04-01 | 66 | 136-0076 | S13037 | 20150414 | 0-00000000-0 |
| CS031415000172 | 宇多田 貴美子 | 1 | 1976-10-04 | 42 | 151-0053 | S13031 | 20150529 | D-20100325-C |
%%sql
-- データの内容確認
SELECT * FROM gender_std LIMIT 3;
* postgresql://padawan:***@db:5432/dsdojo_db 3 rows affected.
| gender_cd | gender |
|---|---|
| 0 | 男性 |
| 9 | 不明 |
| 1 | 女性 |
S-093: 商品データ(product)では各カテゴリのコード値だけを保有し、カテゴリ名は保有していない。カテゴリデータ(category)と組み合わせて非正規化し、カテゴリ名を保有した新たな商品データを作成せよ。
%%sql
DROP TABLE IF EXISTS product_full;
CREATE TABLE product_full AS (
SELECT
p.product_cd,
p.category_major_cd,
c.category_major_name,
p.category_medium_cd,
c.category_medium_name,
p.category_small_cd,
c.category_small_name,
p.unit_price,
p.unit_cost
FROM
product p
JOIN
category c
USING(category_small_cd)
);
* postgresql://padawan:***@db:5432/dsdojo_db Done. 10030 rows affected.
[]
%%sql
-- データの内容確認
SELECT * FROM product_full LIMIT 3;
* postgresql://padawan:***@db:5432/dsdojo_db 3 rows affected.
| product_cd | category_major_cd | category_major_name | category_medium_cd | category_medium_name | category_small_cd | category_small_name | unit_price | unit_cost |
|---|---|---|---|---|---|---|---|---|
| P040101001 | 04 | 惣菜 | 0401 | 御飯類 | 040101 | 弁当類 | 198 | 149 |
| P040101002 | 04 | 惣菜 | 0401 | 御飯類 | 040101 | 弁当類 | 218 | 164 |
| P040101003 | 04 | 惣菜 | 0401 | 御飯類 | 040101 | 弁当類 | 230 | 173 |
S-094: 093で作成したカテゴリ名付き商品データを以下の仕様でファイル出力せよ。
|ファイル形式|ヘッダ有無|文字エンコーディング| |:--:|:--:|:--:| |CSV(カンマ区切り)|有り|UTF-8|
ファイル出力先のパスは以下のようにすること(COPYコマンドの権限は付与済み)。
|出力先| |:--:| |/tmp/data|
※"/tmp/data"を指定することでJupyterの"/work/data"と共有されるようになっている。
%%sql
COPY product_full TO '/tmp/data/S_product_full_UTF-8_header.csv'
WITH CSV HEADER ENCODING 'UTF-8';
* postgresql://padawan:***@db:5432/dsdojo_db 10030 rows affected.
[]
S-095: 093で作成したカテゴリ名付き商品データを以下の仕様でファイル出力せよ。
|ファイル形式|ヘッダ有無|文字エンコーディング| |:--:|:--:|:--:| |CSV(カンマ区切り)|有り|CP932|
PostgreSQLではShift_JISを指定することでCP932相当となる。ファイル出力先のパスは以下のようにすること(COPYコマンドの権限は付与済み)。
|出力先| |:--:| |/tmp/data|
※"/tmp/data"を指定することでJupyterの"/work/data"と共有されるようになっている。
%%sql
COPY product_full TO '/tmp/data/S_product_full_SJIS_header.csv'
WITH CSV HEADER ENCODING 'SJIS';
* postgresql://padawan:***@db:5432/dsdojo_db 10030 rows affected.
[]
S-096: 093で作成したカテゴリ名付き商品データを以下の仕様でファイル出力せよ。
|ファイル形式|ヘッダ有無|文字エンコーディング| |:--:|:--:|:--:| |CSV(カンマ区切り)|無し|UTF-8|
ファイル出力先のパスは以下のようにすること(COPYコマンドの権限は付与済み)。
|出力先| |:--:| |/tmp/data|
※"/tmp/data"を指定することでJupyterの"/work/data"と共有されるようになっている。
%%sql
COPY product_full TO '/tmp/data/S_product_full_UTF-8_noh.csv'
WITH CSV ENCODING 'UTF-8';
* postgresql://padawan:***@db:5432/dsdojo_db 10030 rows affected.
[]
S-097: 094で作成した以下形式のファイルを読み込み、データを3件を表示させて正しく取り込まれていることを確認せよ。
|ファイル形式|ヘッダ有無|文字エンコーディング| |:--:|:--:|:--:| |CSV(カンマ区切り)|有り|UTF-8|
%%sql
DROP TABLE IF EXISTS product_full;
CREATE TABLE product_full (
product_cd VARCHAR(10),
category_major_cd VARCHAR(2),
category_major_name VARCHAR(20),
category_medium_cd VARCHAR(4),
category_medium_name VARCHAR(20),
category_small_cd VARCHAR(6),
category_small_name VARCHAR(20),
unit_price INTEGER,
unit_cost INTEGER
);
* postgresql://padawan:***@db:5432/dsdojo_db Done. Done.
[]
%%sql
COPY product_full FROM '/tmp/data/S_product_full_UTF-8_header.csv'
WITH CSV HEADER ENCODING 'UTF-8';
* postgresql://padawan:***@db:5432/dsdojo_db 10030 rows affected.
[]
%%sql
SELECT * FROM product_full LIMIT 3;
* postgresql://padawan:***@db:5432/dsdojo_db 3 rows affected.
| product_cd | category_major_cd | category_major_name | category_medium_cd | category_medium_name | category_small_cd | category_small_name | unit_price | unit_cost |
|---|---|---|---|---|---|---|---|---|
| P040101001 | 04 | 惣菜 | 0401 | 御飯類 | 040101 | 弁当類 | 198 | 149 |
| P040101002 | 04 | 惣菜 | 0401 | 御飯類 | 040101 | 弁当類 | 218 | 164 |
| P040101003 | 04 | 惣菜 | 0401 | 御飯類 | 040101 | 弁当類 | 230 | 173 |
S-098: 096で作成した以下形式のファイルを読み込み、データを3件を表示させて正しく取り込まれていることを確認せよ。
|ファイル形式|ヘッダ有無|文字エンコーディング| |:--:|:--:|:--:| |CSV(カンマ区切り)|ヘッダ無し|UTF-8|
%%sql
DROP TABLE IF EXISTS product_full;
CREATE TABLE product_full (
product_cd VARCHAR(10),
category_major_cd VARCHAR(2),
category_major_name VARCHAR(20),
category_medium_cd VARCHAR(4),
category_medium_name VARCHAR(20),
category_small_cd VARCHAR(6),
category_small_name VARCHAR(20),
unit_price INTEGER,
unit_cost INTEGER
);
* postgresql://padawan:***@db:5432/dsdojo_db Done. Done.
[]
%%sql
COPY product_full FROM '/tmp/data/S_product_full_UTF-8_noh.csv'
WITH CSV ENCODING 'UTF-8';
* postgresql://padawan:***@db:5432/dsdojo_db 10030 rows affected.
[]
%%sql
SELECT * FROM product_full LIMIT 3;
* postgresql://padawan:***@db:5432/dsdojo_db 3 rows affected.
| product_cd | category_major_cd | category_major_name | category_medium_cd | category_medium_name | category_small_cd | category_small_name | unit_price | unit_cost |
|---|---|---|---|---|---|---|---|---|
| P040101001 | 04 | 惣菜 | 0401 | 御飯類 | 040101 | 弁当類 | 198 | 149 |
| P040101002 | 04 | 惣菜 | 0401 | 御飯類 | 040101 | 弁当類 | 218 | 164 |
| P040101003 | 04 | 惣菜 | 0401 | 御飯類 | 040101 | 弁当類 | 230 | 173 |
S-099: 093で作成したカテゴリ名付き商品データを以下の仕様でファイル出力せよ。
|ファイル形式|ヘッダ有無|文字エンコーディング| |:--:|:--:|:--:| |TSV(タブ区切り)|有り|UTF-8|
ファイル出力先のパスは以下のようにすること(COPYコマンドの権限は付与済み)。
|出力先| |:--:| |/tmp/data|
※"/tmp/data"を指定することでJupyterの"/work/data"と共有されるようになっている。
%%sql
COPY product_full TO '/tmp/data/S_product_full_UTF-8_header.tsv'
WITH CSV HEADER DELIMITER E'\t' ENCODING 'UTF-8';
* postgresql://padawan:***@db:5432/dsdojo_db 10030 rows affected.
[]
S-100: 099で作成した以下形式のファイルを読み込み、データを3件を表示させて正しく取り込まれていることを確認せよ。
|ファイル形式|ヘッダ有無|文字エンコーディング| |:--:|:--:|:--:| |TSV(タブ区切り)|有り|UTF-8|
%%sql
DROP TABLE IF EXISTS product_full;
CREATE TABLE product_full (
product_cd VARCHAR(10),
category_major_cd VARCHAR(2),
category_major_name VARCHAR(20),
category_medium_cd VARCHAR(4),
category_medium_name VARCHAR(20),
category_small_cd VARCHAR(6),
category_small_name VARCHAR(20),
unit_price INTEGER,
unit_cost INTEGER
);
* postgresql://padawan:***@db:5432/dsdojo_db Done. Done.
[]
%%sql
COPY product_full FROM '/tmp/data/S_product_full_UTF-8_header.tsv'
WITH CSV HEADER DELIMITER E'\t' ENCODING 'UTF-8';
* postgresql://padawan:***@db:5432/dsdojo_db 10030 rows affected.
[]
%%sql
SELECT * FROM product_full LIMIT 3;
* postgresql://padawan:***@db:5432/dsdojo_db 3 rows affected.
| product_cd | category_major_cd | category_major_name | category_medium_cd | category_medium_name | category_small_cd | category_small_name | unit_price | unit_cost |
|---|---|---|---|---|---|---|---|---|
| P040101001 | 04 | 惣菜 | 0401 | 御飯類 | 040101 | 弁当類 | 198 | 149 |
| P040101002 | 04 | 惣菜 | 0401 | 御飯類 | 040101 | 弁当類 | 218 | 164 |
| P040101003 | 04 | 惣菜 | 0401 | 御飯類 | 040101 | 弁当類 | 230 | 173 |