概要: 本記事では、SQLのDISTINCT, BETWEEN, LIKE, PARTITIONといった重要なデータ操作キーワードの基本的な使い方から応用例までを網羅的に解説します。重複排除、範囲指定、部分一致検索、データ差分抽出など、多岐にわたるデータ処理を効率的に行うための知識を習得できます。よくある失敗例とその対処法も紹介し、より実践的なSQLスキル向上を目指しましょう。
SQLデータ操作を効率化するDISTINCT, BETWEEN, LIKEの基本戦略
SQLスキルがビジネスで不可欠な理由と市場価値
現代のビジネス環境において、データに基づいた意思決定は企業の競争力を左右する重要な要素です。このデータ駆動型のアプローチを支えるのがSQLスキルであり、職種を問わずその需要は急速に高まっています。経済産業省の推計によると、IT人材は2030年までに最大で約79万人不足する可能性があり、特にデータ活用やDX推進を担う人材の市場価値は今後も向上すると見込まれています。データ分析の専門家だけでなく、営業、マーケティング、企画といった職種のビジネスパーソンにとっても、SQLを使いこなす能力は自身の市場価値を高める強力な武器となるでしょう。
実際、プロフェッショナル開発者の約52%が実務でSQLを使用しているというStack Overflow Developer Survey 2024のデータからも、その汎用性と重要性が伺えます。また、SQLスキルを持つエンジニアの平均年収は、日本の給与所得者の平均478万円(国税庁 令和6年分 民間給与実態統計調査)を上回る450万〜650万円程度が一般的とされており、専門性の高さが給与水準にも反映されています。AI技術の進化により、SQLのコード生成自体は容易になりつつありますが、生成されたクエリの意図を理解し、データ構造を把握した上で適切に修正・最適化する能力は、依然として人間の専門性に強く依存します。
DISTINCTによるデータ重複排除の基本原則
データ分析やレポート作成において、重複したデータは集計結果を歪め、誤った意思決定を招く可能性があります。例えば、ウェブサイトへのユニーク訪問者数をカウントする際に、同一ユーザーが複数回アクセスしたデータをそのまま集計してしまうと、実態よりも多くの訪問者数が計上されてしまいます。このような問題を解決するためにSQLのDISTINCTキーワードが役立ちます。DISTINCTは、指定した列または列の組み合わせにおいて、重複しないユニークな値のみを抽出するために使用されます。
基本的な構文は「SELECT DISTINCT column_name FROM table_name;」となり、このクエリを実行することで、指定したcolumn_nameに含まれる重複する値がすべて排除され、一意の値だけがリストアップされます。例えば、顧客リストからユニークな都道府県名を抽出したい場合、「SELECT DISTINCT prefecture FROM customers;」と記述します。複数の列を指定した場合、「SELECT DISTINCT column_name1, column_name2 FROM table_name;」のように記述すると、指定した列の組み合わせが完全に一致する行が重複とみなされ、一意の組み合わせのみが抽出されます。この機能は、正確な顧客セグメンテーションや商品カテゴリの重複排除など、様々なビジネスシーンで不可欠なデータクレンジングの第一歩となります。
BETWEENとLIKEによるデータ絞り込みの基礎
大量のデータの中から特定の条件に合致する情報を効率的に見つけ出すには、適切な絞り込み条件の設定が不可欠です。SQLのBETWEEN演算子とLIKE演算子は、それぞれ異なるアプローチでデータの絞り込みを可能にします。BETWEENは、数値、日付、または文字列の範囲を指定してデータを抽出する際に使用されます。例えば、特定期間の売上データや、特定の価格帯の商品を検索する際に非常に有効です。構文は「SELECT * FROM table_name WHERE column_name BETWEEN value1 AND value2;」となり、value1とvalue2の両端の値を含んだ範囲でデータが抽出されます。
一方、LIKE演算子は、文字列の部分一致検索を行う際に用いられます。検索したい文字列の一部しか分からない場合や、特定のパターンに合致するデータを抽出したい場合に強力なツールとなります。LIKE演算子と組み合わせて使用されるワイルドカードには、「%」(任意の位置に任意の文字が0回以上続く)と「_」(任意の位置に任意の文字が1文字だけ入る)があります。例えば、「SELECT * FROM products WHERE product_name LIKE '%シャツ%';」と記述すれば、商品名に「シャツ」という文字列を含むすべての商品が抽出されます。これらの演算子を適切に使いこなすことで、目的に応じた柔軟かつ精度の高いデータ抽出が可能となり、分析作業の効率が格段に向上します。
出典:IT人材需給に関する調査(経済産業省 / 2019年3月)、Stack Overflow Developer Survey 2024(Stack Overflow / 2024年)、令和6年分 民間給与実態統計調査(国税庁 / 2025年)、SQLエンジニアとは?仕事内容や必要なスキルなど徹底解説(Brucke / 2026年)
- DISTINCTで意図通りの重複排除ができているか、必ず確認していますか?
- BETWEENで日付範囲を指定する際、時刻の考慮漏れはありませんか?
- LIKEで部分一致検索をする際、ワイルドカード(%_)を正しく使えていますか?
- SQLクエリを記述する前に、対象データの構造を理解していますか?
- AI生成クエリのレビューとパフォーマンス最適化の知識を磨いていますか?
重複排除、範囲指定、部分一致検索を実装するステップ
DISTINCTを使った重複行の識別と除去
DISTINCTキーワードは、テーブルから重複のない一意なデータを抽出するための強力なツールです。例えば、顧客が複数回商品を購入している場合に、ユニークな顧客IDのリストだけを取得したいとします。この場合、「SELECT DISTINCT customer_id FROM orders;」というシンプルなクエリで、重複する顧客IDを排除したリストが得られます。これにより、実顧客数を正確に把握し、マーケティング施策の効果測定などに活用できます。また、複数の列を組み合わせて重複を判断したい場合は、「SELECT DISTINCT customer_id, product_name FROM orders;」のように複数の列を指定します。この場合、customer_idとproduct_nameの組み合わせが完全に一致する行のみが重複とみなされ、一意な組み合わせが抽出されます。
重複行の識別には、COUNT(*)と組み合わせて利用する方法も有効です。例えば、あるテーブルでcolumn_nameに重複が存在するか確認するには、「SELECT column_name, COUNT(*) FROM table_name GROUP BY column_name HAVING COUNT(*) > 1;」というクエリを実行することで、重複しているcolumn_nameの値と、その重複回数を特定できます。この識別作業を通じて、データの品質問題を発見し、DISTINCTを使った重複除去や、より複雑なデータクレンジング戦略を計画するための具体的なステップを踏むことが可能になります。
BETWEENで特定範囲のデータを抽出する手順
BETWEEN演算子は、数値や日付、さらには文字列の範囲に基づいてデータを絞り込む際に非常に役立ちます。例えば、特定の価格帯の商品を一覧表示したい場合、「SELECT product_name, price FROM products WHERE price BETWEEN 1000 AND 5000;」と記述することで、1000円から5000円(両端を含む)の商品だけを効率的に抽出できます。このクエリは、プロモーション対象商品の選定や、在庫管理における特定の価格レンジ商品の分析に活用できるでしょう。
日付の範囲指定においてもBETWEENは頻繁に使用されます。例えば、2023年1月中に発生した全ての注文データを取得するには、「SELECT * FROM sales WHERE order_date BETWEEN '2023-01-01' AND '2023-01-31';」と記述します。ここで注意すべきは、データベースによっては日付型データに時間情報が含まれる場合、最終日(例: ‘2023-01-31’)の00:00:00以降のデータが抽出されない可能性がある点です。より厳密な日付範囲を指定するには、「WHERE order_date >= '2023-01-01' AND order_date < '2023-02-01';」のように、>=と<を組み合わせて使用する方法も考慮に入れると良いでしょう。これにより、特定のレポート期間に確実に合致するデータを抽出できます。
LIKE演算子で部分一致検索を行う方法
LIKE演算子は、文字列データに対して柔軟な部分一致検索を可能にします。特に、ユーザー入力の検索機能や、特定の命名規則を持つデータを抽出する際に重宝されます。LIKEと組み合わせて使用するワイルドカードは主に二種類あります。
%(パーセント): 0文字以上の任意の文字列にマッチします。_(アンダースコア): 1文字の任意の文字にマッチします。
例えば、商品名に「トップス」という単語が含まれる商品を検索したい場合、「SELECT product_name FROM products WHERE product_name LIKE '%トップス%';」と記述します。これにより、「カジュアルトップス」「トップスコレクション」「春のトップス」といった商品名がすべて抽出されます。もし「Tシャツ」のように、最初の文字は任意だが、2文字目以降が「シャツ」である商品を検索したい場合は、「SELECT product_name FROM products WHERE product_name LIKE '_シャツ%';」と記述することで、より特定のパターンに絞り込んだ検索が可能です。
データベースによっては、LIKE検索が大文字・小文字を区別する場合としない場合があります。大文字・小文字を区別せずに検索したい場合は、LOWER()関数やUPPER()関数を使って列の値を変換するか、データベース固有のILIKE(PostgreSQLなど)などの演算子を利用することを検討してください。これらのワイルドカードと関数の組み合わせにより、目的に応じた複雑な文字列検索を効率的に実行できます。
データ重複排除から差分抽出まで!実践的な応用クエリ集
複数の条件を組み合わせた高度なデータ抽出テクニック
DISTINCT、BETWEEN、LIKEはそれぞれ強力なキーワードですが、これらを組み合わせて使用することで、より複雑で具体的なビジネス要件に対応するデータ抽出が可能になります。例えば、「過去3ヶ月以内に、特定の地域からの問い合わせで、かつ問い合わせ内容に『不具合』というキーワードが含まれる、重複しない顧客の連絡先を抽出したい」といったケースを考えてみましょう。この場合、WHERE句の中でBETWEENで日付範囲を指定し、LIKEで問い合わせ内容を絞り込み、さらに全体の結果に対してDISTINCTを使ってユニークな顧客情報を取得する、という複合的なクエリを組み立てます。
具体的には、「SELECT DISTINCT customer_id, customer_email FROM inquiries WHERE inquiry_date BETWEEN 'YYYY-MM-DD' AND 'YYYY-MM-DD' AND region = '特定の地域' AND inquiry_content LIKE '%不具合%';」のようなクエリが考えられます。このように、複数の条件を論理演算子(AND, OR)で組み合わせることで、詳細なデータセグメンテーションを実現し、よりターゲットを絞った分析やアクションプランの策定を支援します。データの量が膨大になるほど、このような正確な絞り込みは分析の精度を向上させ、無駄なリソース消費を防ぐ上で非常に重要となります。
データの差分抽出と更新確認における活用
データ分析では、時間経過によるデータの変化や、新旧データの差分を抽出する場面が頻繁にあります。DISTINCT、BETWEEN、LIKEは、このような差分抽出や更新確認のプロセスでも有効活用できます。例えば、前月と今月の顧客データテーブルを比較し、新しく登録された顧客を特定したい場合、LEFT JOINとWHERE IS NULL、そしてDISTINCTを組み合わせることで、効率的に差分を抽出できます。
「SELECT DISTINCT A.customer_id FROM current_month_customers A LEFT JOIN previous_month_customers B ON A.customer_id = B.customer_id WHERE B.customer_id IS NULL;」のようなクエリで、今月に追加されたユニークな顧客IDのリストが得られます。また、商品マスタの更新履歴を追う際に、LIKE演算子を使って、特定のキーワードが含まれる商品名がどのように変更されたかを確認することも可能です。例えば、「旧商品名に『限定』とあったが、新商品名ではその表記が変更された商品」などを検索し、更新の背景を分析することができます。これらの手法は、データの整合性チェックや、ビジネス指標の動向分析において重要な役割を果たします。
SQL前処理としてのDISTINCT, BETWEEN, LIKE
データエンジニアやデータサイエンティストは、分析の基盤を構築する上で、生データを分析に適した形に「前処理」する作業を担います。この前処理の段階で、DISTINCT、BETWEEN、LIKEといったSQLキーワードは欠かせないツールとなります。例えば、顧客データに重複するIDが含まれていれば、DISTINCTを用いてユニークなIDを特定し、重複行の整理を行います。また、日付や数値の範囲が異常値を含んでいないか、BETWEENを使って検証し、必要に応じて除外したり補正したりします。
さらに、商品名や住所、自由記述欄のテキストデータなどに表記揺れや誤字が含まれる場合、LIKE演算子を活用して特定のパターンを検出し、統一された表記にクレンジングする作業も行われます。例えば、「株式会社」が「(株)」と略されているデータをLIKEで探し出し、一括で正規化するなどが考えられます。これらの前処理によって、データの欠損補完、重複整理、表記揺れの統一が行われ、分析結果の信頼性を高める土台が築かれます。SQLは単なるデータ抽出ツールではなく、データ品質を担保し、分析基盤を堅牢にするための強力な武器となります。
出典:職業情報提供サイト(job tag)「データエンジニア」(厚生労働省 / 更新日不詳)
各キーワード利用時の注意点とパフォーマンス改善策
DISTINCT利用時のパフォーマンス影響と最適化
DISTINCTキーワードは非常に便利ですが、大量のデータに対して使用する際には、パフォーマンスに大きな影響を与える可能性があります。これは、データベースがすべての行をスキャンし、重複を識別・排除するためにソートやハッシュ処理を行う必要があるためです。特に、DISTINCTを適用する列が多い場合や、対象となるテーブルの行数が極めて多い場合には、クエリの実行時間が長くなる傾向があります。このため、DISTINCTを使用する際は、本当に必要な列だけに限定し、不必要な列を含めないよう注意が必要です。
パフォーマンスを改善するための一つの方法は、対象の列に適切なインデックスが貼られているか確認することです。インデックスが存在すれば、データベースは重複の特定やソート処理をより効率的に行える可能性があります。ただし、複数の列に対してDISTINCTを使用する場合、その組み合わせをカバーする複合インデックスが必要になることもあります。また、可能であれば、データを事前にフィルタリングして対象行数を減らしてからDISTINCTを適用する、あるいは一時テーブルに絞り込んだデータを格納してからDISTINCT処理を行うといった工夫も有効です。クエリチューニングツールやEXPLAINコマンドを活用し、実行計画を分析することで、パフォーマンスボトルネックを特定し、具体的な改善策を見つけることができます。
BETWEENとLIKE利用時のインデックス活用戦略
BETWEEN演算子とLIKE演算子の利用時も、クエリのパフォーマンスはインデックスの有無と種類に大きく左右されます。BETWEENは範囲検索であるため、対象の列にB-treeインデックスが貼られている場合、そのインデックスを効率的に利用して高速なデータアクセスが可能です。特に日付や数値の範囲指定において、インデックスは非常に有効な手段となります。日付型の列であれば、order_date BETWEEN '2023-01-01' AND '2023-01-31'のようなクエリはインデックスの恩恵を受けやすいでしょう。
一方、LIKE演算子については、インデックスの活用に注意が必要です。前方一致検索(例: LIKE 'キーワード%')の場合、B-treeインデックスは比較的有効に機能し、検索速度を向上させることが期待できます。しかし、中間一致(例: LIKE '%キーワード%')や後方一致(例: LIKE '%キーワード')の場合、従来のB-treeインデックスはほとんど機能せず、フルスキャンに近い状態となり、パフォーマンスが著しく低下する可能性があります。このような場合は、データベースによっては全文検索インデックス(Full-Text Index)の導入を検討するか、アプリケーション側での処理を工夫するといったアプローチが必要になることがあります。どの検索パターンでインデックスが効くかを理解し、適切なインデックス戦略を立てることが重要です。
AIによるSQL生成と人間の役割の再確認
近年、AI技術の進化により、自然言語で指示するだけでSQLクエリを自動生成するツールが普及しつつあります。これにより、SQLの記述自体にかかる時間は短縮され、非専門家でもデータにアクセスする機会が増えました。しかし、AIが生成したSQLクエリが常に最適なものとは限りません。AIは、提示されたデータモデルと指示に基づいて構文的に正しいクエリを生成しますが、そのクエリがデータベースの特性(インデックス、データ量、結合パターンなど)を最大限に活かし、パフォーマンスを最適化しているとは限りません。
したがって、SQLエンジニアやデータアナリストには、AIが生成したクエリの適切性を評価し、パフォーマンス上の問題がないかを検証する能力が強く求められます。具体的には、生成されたクエリの実行計画を分析し、より効率的な書き方を提案したり、不足しているインデックスを特定したりする役割が重要です。また、「どのテーブルから」「どのような条件で」データを取得すべきかというデータ構造の深い理解は、AIには代替できない人間の専門領域です。AIを単なるコードジェネレーターとして利用するだけでなく、その出力をレビューし、最適化する「最後の砦」として人間のスキルは今後も不可欠であり続けるでしょう。
【ケース】複雑なデータ抽出で発生した問題とその改善アプローチ
架空のケース:データ重複による売上集計の誤り
あるEコマース企業で、月次売上レポートを作成する際、特定のキャンペーン期間中のユニーク顧客数と平均購入単価が、実際のキャンペーン効果よりも高く計上されている問題が発生しました。調査の結果、システム連携の際に顧客IDが一時的に重複して登録され、その重複したIDがレポート集計にそのまま利用されていたことが判明しました。これにより、一人の顧客が複数人としてカウントされ、正確なビジネス判断を妨げるリスクがありました。この問題は、特に初回購入キャンペーンなどの成果測定において、顧客数の過大評価に繋がりやすいため、早急な改善が求められました。
改善アプローチ:問題解決のため、売上集計クエリの顧客IDに関する部分にDISTINCTキーワードを適用しました。具体的には、「SELECT COUNT(DISTINCT customer_id) FROM orders WHERE order_date BETWEEN 'キャンペーン開始日' AND 'キャンペーン終了日';」のようにクエリを修正しました。これにより、重複する顧客IDが排除され、キャンペーン期間中の真のユニーク顧客数を正確に把握できるようになりました。また、今後のデータ取り込みプロセスにおいて、定期的に重複チェックを行うスクリプトを追加し、データ品質を維持する仕組みを構築しました。この改善により、キャンペーン効果の正確な評価が可能となり、次のマーケティング戦略立案に貢献することができました。
架空のケース:期間指定と部分一致検索の組み合わせミス
とあるソフトウェア開発会社で、特定の製品群に対するユーザーからのフィードバックを分析する際、キャンペーン期間中のフィードバック数が期待値よりも少なく報告される問題が発生しました。調査の結果、原因はデータ抽出クエリにおける期間指定と部分一致検索の組み合わせミスにあることが判明しました。具体的には、BETWEENで日付範囲を指定する際に、最終日の時刻が考慮されていなかったため、最終日中のフィードバックの一部が抽出漏れとなっていました。さらに、製品名の一部をLIKE '%製品名%'で検索していたものの、ユーザーの入力揺れや略称に対応できておらず、関連フィードバックを見逃している可能性がありました。
改善アプローチ:まず、日付範囲の指定を「WHERE feedback_date >= 'キャンペーン開始日' AND feedback_date < 'キャンペーン終了日の翌日'」と修正し、最終日を含む全てのフィードバックが抽出されるようにしました。次に、LIKE検索については、製品名の表記揺れパターン(例:「製品A」「製品エー」「Product A」)を事前に洗い出し、複数のLIKE条件をORで繋ぐ、または正規表現関数(データベース依存)を使用するなどして、網羅性を高めました。これにより、キャンペーン期間中の全ての関連フィードバックを正確に抽出し、製品改善に繋がる貴重なインサイトを得ることができました。このケースから、細かな日付処理の考慮や、柔軟な文字列検索の設計が、データ分析の精度を大きく左右することが改めて認識されました。
パフォーマンス問題に直面した際のトラブルシューティング
データ分析部門で、日次レポート生成用のSQLクエリの実行時間が突然大幅に増加し、業務に支障をきたす問題が発生しました。このクエリは複数の大規模テーブルを結合し、WHERE句でLIKE '%キーワード%'のような中間一致検索と、複雑なDISTINCT処理を組み合わせたものでした。問題発生の背景には、対象データ量の増加と、特定の列に対するインデックス不足が考えられました。レポート生成に数時間かかるようになり、タイムリーな意思決定が困難となっていました。
改善アプローチ:まず、EXPLAINコマンド(またはデータベース固有の実行計画表示ツール)を使用して、クエリの実行計画を詳細に分析しました。その結果、LIKE '%キーワード%'の部分がフルテーブルスキャンを引き起こしていること、そしてDISTINCT処理がソートに多大な時間を要していることが判明しました。改善策として、LIKE検索の対象となる列に全文検索インデックス(利用可能な場合)の導入を検討しました。また、DISTINCT処理の前段階で、必要な列と行だけをサブクエリで先に絞り込むことで、処理対象のデータ量を最小限に抑えました。さらに、頻繁に結合される列には複合インデックスを適用し、結合処理の効率化を図りました。これらの対策により、レポート生成時間は数時間から数分へと大幅に短縮され、日次でのデータ活用が再びスムーズに行えるようになりました。
まとめ
よくある質問
Q: SQL DISTINCTとは具体的にどのような機能ですか?
A: DISTINCT句は、SELECT文で取得する結果セットから重複する行を全て取り除き、一意な値のみを表示する機能です。特定のカラムだけでなく、選択されたすべてのカラムの組み合わせで重複を判定します。
Q: SQLのBETWEEN句は日付範囲以外にも使えますか?
A: はい、BETWEEN句は数値や文字列の範囲指定にも利用できます。例えば、`WHERE price BETWEEN 100 AND 200`のように価格帯を指定したり、`WHERE name BETWEEN ‘A’ AND ‘C’`でアルファベット順の範囲を絞り込むことも可能です。
Q: SQLの部分一致検索で「%」と「_」の使い分けを教えてください?
A: `%`は0文字以上の任意の文字列に一致するワイルドカードで、`_`は1文字の任意の文字に一致します。例えば、`LIKE ‘A%’`は「A」で始まる全てに一致し、`LIKE ‘A_B’`は「A」で終わる3文字の文字列に一致します。
Q: SQLで重複データを見つけて削除する方法はありますか?
A: 重複データを特定するには`GROUP BY`句と`HAVING COUNT(*) > 1`を組み合わせます。削除する場合は、一時テーブルを利用するか、`CTE`や`ROW_NUMBER()`と`DELETE`文を組み合わせて、重複する行のうち必要な1行を残し他を削除します。
Q: SQL PARTITION BY句はどのような時に役立ちますか?
A: PARTITION BY句は、ウィンドウ関数と組み合わせて使用し、データを特定のグループに分割して各グループ内で集計やランキングを行う際に役立ちます。例えば、部署ごとの売上合計や、顧客ごとの購入履歴の最新N件を取得するのに便利です。
