今回の課題・得点と最高完了得点をこのブラウザに保存します。SQL入力・実行結果・教材DBへの変更は再読み込みで戻ります。誤答やヒントによる減点はありません。
最高完了得点: 0 / 100pt
90日分の売上データで店舗・月ごとの売れ筋上位3商品を抽出。同率を含むRANKとDENSE_RANKの違い、集計後の順位と絞り込みを、SQLiteを実行する3問で練習します。
売上明細の金額が高い1行と、月間合計が高い商品は別です。まず
月・店舗・商品で集計し、その結果に順位を付け、最後に上位だけを取り出す順序で考えます。
daily_salesは90日分・2店舗・563行の練習用データです。実在の店舗の実績ではありません。
商品名はproductsのidとproduct_idを結合して調べられますが、この3問では商品IDを返します。
WITH totals AS (
SELECT strftime('%Y-%m', sale_date) AS month, store, product_id, SUM(amount) AS sales
FROM daily_sales GROUP BY month, store, product_id
), ranked AS (
SELECT month, store, product_id, sales,
ROW_NUMBER() OVER (PARTITION BY month, store ORDER BY sales DESC, product_id) AS rn
FROM totals
)
SELECT month, store, product_id, sales, rn FROM ranked
WHERE rn <= 3 ORDER BY month, store, rn;
PARTITION BY month, storeで6つのグループに分けます。売上が同じときも
product_idの小さい順を指定して、ROW_NUMBERの選び方を固定します。
このデータでは各グループに3商品以上あるので、結果は6×3の18行です。
2026年3月の東京本店は商品5が1,155,000円、商品6が980,000円、商品10が945,000円です。
LIMIT 3は結果全体の3行しか残しません。店舗を区切らない順位では、東京の売上で
大阪の商品が押し出されます。月も区切らなければ、違う月の商品を同じ順位で比較します。
2026-03-15の東京本店には、商品5と10がともに105,000円、商品1が98,000円という
同率の例があります。店舗・商品ごとのその日の売上で比べます。
| 商品ID | 売上 | RANK | DENSE_RANK |
|---|---|---|---|
| 5 | 105000 | 1 | 1 |
| 10 | 105000 | 1 | 1 |
| 1 | 98000 | 3 | 2 |
RANKは同率の人数を数えて次の順位を飛ばします。DENSE_RANKは異なる値を数え、順位を飛ばしません。
ROW_NUMBERは同率でも別番号です。「上位2行」「競技順位の2位以内」
「売上金額の上位2段階」は異なる条件です。要件に合わせて選びます。
WITH totals AS (
SELECT store, product_id, SUM(amount) AS sales
FROM daily_sales WHERE sale_date = '2026-03-15' GROUP BY store, product_id
)
SELECT store, product_id, sales,
RANK() OVER (PARTITION BY store ORDER BY sales DESC) AS rnk,
DENSE_RANK() OVER (PARTITION BY store ORDER BY sales DESC) AS dense
FROM totals ORDER BY store, sales DESC, product_id;
同率を残す順位のORDER BYにproduct_idを加えると、金額が同じでも別の値の組と扱われ、
同率が消えます。順位は売上だけ、表示順は売上と商品IDと分けてください。
ROW_NUMBERで件数を固定する場合の決め方とは違います。
WITH totals AS (
SELECT store, product_id, SUM(amount) AS sales
FROM daily_sales WHERE sale_date = '2026-03-15' GROUP BY store, product_id
), ranked AS (
SELECT store, product_id, sales,
DENSE_RANK() OVER (PARTITION BY store ORDER BY sales DESC) AS dense
FROM totals
)
SELECT store, product_id, sales, dense FROM ranked
WHERE dense <= 2 ORDER BY store, dense, product_id;
ここでは売上金額の上位2段階を残すので、東京は同率1位2商品と2位1商品の計3行、
大阪は2行、全体で5行です。RANKの2位以内では東京の98,000円が消えます。
ウィンドウ関数を計算するSELECTと同じ段階のWHEREでは、その順位を条件にできません。
CTEかサブクエリで包んで、外側で絞ります。
- 集計単位は明細ではなく、問1は月・店舗・商品、問2・3は指定日・店舗・商品です。
- 返す列名と順序、行の並び順も問題文に指定しています。別のSQL構成でも同じ結果なら正解です。
- 正しい件数だけでは採点しません。全行の店舗・商品・売上・順位と列名を確認します。
- ORDER BYのない結果順は保証されません。問題文どおり、最後のSELECTにも並び順を書きます。
- 売上ゼロで記録のない商品はこの集計に出ません。ゼロ商品を含むランキングは別の要件です。
構文の定義はSQLite公式のwindowfunctions.htmlのRanking Functionsを参照。
数値はこの練習データに対する結果で、実在の業務判断を示すものではありません。
結果は1000行まで・実行は30秒まで。中止・リセットは教材への変更だけを破棄し、入力SQLと進捗は残します。
教材DBを初期化しています。