SQL UNION と UNION ALL: 違い、例、テストされたパフォーマンス
それらの違いは 1 語ですが、間違った選択をすると、間違った合計が表示される可能性があります。実際のデータで両方を確認し、それらに共通するルールを学び、100 万行で時間を計測したときに何が起こったのかを読んでください。
UNION結果を結合し、重複する行を削除します。UNION ALLはすべての行を保持します。- 重複排除にはコストがかかるため、通常は
UNION ALLの方が計算が速くなります。 SUMの前にUNIONを使用すると、実際の値が暗黙的に削除され、間違った答えが得られる可能性があります。- 特に重複を削除する必要がない限り、デフォルトは
UNION ALLです。
どちらの演算子も 2 つのクエリの結果を互いに積み重ねるため、SQL UNION と UNION ALL はマイナーな選択肢のように見えるかもしれません。そうではない。一言追加すると、結果とデータベースの動作負荷の両方が変わります。
ここではすべてのクエリを SQLite 3.50 で実行し、表示された結果とタイミングはそれらの実行からのものです。基本的な動作は、主要なデータベースにわたる標準 SQL です。ただし、タイミングは独自のデータベース、データ、ハードウェアによって異なるため、ここでのタイミングは一例として扱ってください。
短い答え
UNION は 2 つの結果セットを結合し、異なる行のみを返します。 UNION ALL はそれらを結合し、重複を含むすべてを返します。それがすべての違いであり、この記事の残りの部分では、それがなぜ重要なのかについて説明します。
UNION と UNION ALL を並べて表示
| アスペクト | ユニオン | すべてを結合する |
|---|---|---|
| 重複した行 | 削除されました | 保たれた |
| 余分な作業 | 重複を見つける必要がある | なし |
| 通常の速度 | 遅い | より速く |
| 返された行 | 同じかそれ以下 | それらすべて |
| SUM または COUNT の前に安全ですか? | 多くの場合そうではありません | はい |
| こんな方に最適 | 固有のリスト | データ、ログ、合計の結合 |
サンプルデータ
オンラインでの注文と店舗での注文を別のテーブルに保管している店を想像してください。 Asha には同じオンライン注文が 2 つあり、店舗で同じ注文が 1 つあることに注意してください。
CREATE TABLE online_orders (customer TEXT, total INT);
CREATE TABLE store_orders (customer TEXT, total INT);
INSERT INTO online_orders VALUES ('Asha',100), ('Ben',200), ('Asha',100);
INSERT INTO store_orders VALUES ('Asha',100), ('Dev',300);
違いを見てください
SELECT customer, total FROM online_orders
UNION
SELECT customer, total FROM store_orders;
-- Asha | 100
-- Ben | 200
-- Dev | 300
SELECT customer, total FROM online_orders
UNION ALL
SELECT customer, total FROM store_orders;
-- Asha | 100
-- Ben | 200
-- Asha | 100
-- Asha | 100
-- Dev | 300
UNION で入力行 5 行が 3 行になり、UNION ALL で 5 行すべてが残りました。注意すべき 2 つの点:
UNION最初のテーブル内のものも含め、結果全体から重複を削除しました。テーブル間の比較だけではありません。- 行は、選択されたすべての列が一致する場合にのみ重複としてカウントされます。
本当に個別のリストが必要な場合は、UNION が正確です。これにより、いずれかのチャネルを通じて購入したすべての顧客に次の特典が提供されます。
SELECT customer FROM online_orders
UNION
SELECT customer FROM store_orders;
-- Asha
-- Ben
-- Dev
合計が間違っているバグ
これが、選択が本当に重要である理由です。総収益が必要だとします。上記の注文を合計すると 800 になります。各演算子が何を与えるかを確認してください。
SELECT SUM(total) FROM (
SELECT total FROM online_orders
UNION
SELECT total FROM store_orders
);
-- 600
SELECT SUM(total) FROM (
SELECT total FROM online_orders
UNION ALL
SELECT total FROM store_orders
);
-- 800
UNION バージョンは 200 間違っています。total 列のみを選択したため、3 つの別々の 100 ルピー注文が重複のように見え、1 つに折りたたまれました。エラー メッセージはなく、600 という数字は完全に信頼できる数字のように見えます。この種の静かなバグは、財務報告書に何か月も残る可能性があります。
ヒント: 見た目が同じ 2 つの行は、2 つの本物のイベントである可能性があります。 UNION を使用する前に、同一の行が 2 回記録された同じファクトを意味するのか、それとも 2 つの異なるファクトを意味するのかを検討してください。販売、支払い、ログエントリの場合、通常は 2 番目です。
両方が従わなければならないルール
どちらの演算子にも同じ要件があります。
- 各
SELECTは 同じ数の列 を返さなければなりません。 - 列は名前ではなく position によって照合されるため、同じ順序を維持してください。
- 各位置のデータ型は互換性である必要があります。
- 結果の列名は first
SELECTから取得されます。 ORDER BYは最後にあり、結果全体に適用されます。
最初のルールに違反するとエラーが発生します。 SQLite からのメッセージは次のとおりです。
SELECT customer, total FROM online_orders
UNION
SELECT customer FROM store_orders;
-- SELECTs to the left and right of UNION do not have
-- the same number of result columns
2 番目のルールは、エラーなしで失敗する可能性があるため、より危険です。同じタイプの 2 つの列 (first_name と last_name など) を交換すると、クエリが実行され、データが間違ったものになります。 SQLite は型に関しても緩和されていますが、PostgreSQL などのデータベースはより厳密で、明示的な型が必要になる場合があります CAST。
ソースにラベルを付ける
非常に実用的なトリックは、各行がどこから来たのかを示す定数列を追加することです。ラベルが異なるため、異なるテーブルの行を相互の重複として扱うことができなくなりました。
SELECT customer, total, 'online' AS channel FROM online_orders
UNION ALL
SELECT customer, total, 'store' FROM store_orders
ORDER BY customer, channel;
-- Asha | 100 | online
-- Asha | 100 | online
-- Asha | 100 | store
-- Ben | 200 | online
-- Dev | 300 | store
データにラベルを付けたら、GROUP BY を使用してデータをグループ化し、チャネルごとに売上をレポートできます。複数のステップを組み合わせる必要がある場合は、共用体を CTE でラップして読み取り可能に保ちます。
パフォーマンス: テストで何が起こったか
重複を削除するには、データベースは通常、行を並べ替えたりハッシュしたりして行を比較する必要があります。 UNION ALL はこのステップを省略できます。それぞれ 500,000 行のテーブルを 2 つ作成し、0 ~ 50,000 の乱数を含めたので、重複がたくさんありました。各クエリを数回実行し、最良の時間を維持しました。
まず、プログラムに行を送り返すのに費やした時間が比較に影響しないように、結果をカウントしました。
| COUNT(*) でラップされたクエリ | 行 | ベストタイム |
|---|---|---|
| ユニオン | 50,001 | 261ミリ秒 |
| すべてを結合する | 1,000,000 | 1ms未満 |
この大きな差は、SQLite がすべての行を読み取らなくてもそのカウントを計算できることが原因の 1 つであるため、これを「数千倍高速」と解釈しないでください。ただし、これは核となるアイデアを示しています。UNION は実際の作業を行う必要があり、UNION ALL は実際の作業を行わなかったのです。
次に、すべての行を Python にフェッチすると、結果が反転しました。
| クエリ、すべての行のフェッチ | 返された行 | ベストタイム |
|---|---|---|
| ユニオン | 50,001 | 277ミリ秒 |
| すべてを結合する | 1,000,000 | 392ミリ秒 |
ここで、UNION ALL は 20 倍の行を配信したため、さらに時間がかかりました。重複排除が速度を低下させたわけではありません。 100 万行を処理するというものでした。したがって、正直なルールとしては、UNION ALL の方がデータベースの計算コストは安くなりますが、結果のサイズも重要になります。オンラインの多くのチャートでは、これを「UNION ALL は常に高速である」と単純化していますが、私たちのテストは、なぜそれがそれほど単純ではないのかを示しています。
また、速度だけを重視して選択しないでください。最初に正しい答えを与える演算子を選択してから調整します。クエリが遅い場合は、SQL クエリの最適化 に関するガイドをお読みください。
それぞれをいつ使用するか
次の場合に UNION ALL を使用します。
- 月次パーティションなど、類似したテーブルのデータをマージしています。
- その後、合計またはカウントを計算します。
- 入力は重複できないことがわかります。
- ログや監査レコードのように、重複には意味があります。
次の場合に UNION を使用します。
- 2 つのシステムにわたるすべての電子メール アドレスなど、一意のリストが必要です。
- 重複するソースには、同じ事実が複数回含まれています。
UNION ALL をデフォルトとして扱い、UNION を意図的に使用してください。各ブランチに WHERE 句を追加して早期にフィルタリングすると、両方の効果が得られます。
交差と除外
関連する 2 つの集合演算子が、異なる質問に答えます。どちらも同じ列規則に従います。
SELECT customer FROM online_orders
INTERSECT
SELECT customer FROM store_orders;
-- Asha (bought in both channels)
SELECT customer FROM online_orders
EXCEPT
SELECT customer FROM store_orders;
-- Ben (online only)
Oracle は伝統的に EXCEPT ではなく MINUS を使用しており、これらの演算子のサポートはデータベースやバージョンによって多少異なります。
UNION vs JOIN
これらはよく混同されますが、データを異なる方向に結合します。
| 操作 | 方向 | 結果 |
|---|---|---|
| ユニオン | 垂直 | さらに行を追加します |
| 参加する | 水平 | さらに列を追加します |
よくある間違い
- 習慣的に UNION を使用します。 速度が低下したり、有効な行が削除されたりする可能性があります。
- 選択した列が少なすぎます。 ID を省略すると、個別の行が同一に見えます。
- 列の順序が一致していません。 値がエラーなしで間違った列に配置される場合があります。
- 各ブランチに ORDER BY を追加します。 最後に 1 回ソートします。
- UNION を使用して不正な結合をパッチします。 結合が原因で重複が表示される場合は、結合を修正します。
- 結果の順序を仮定します。
ORDER BYを使用しない場合、どちらの演算子でも行の順序は保証されません。
まとめ
毎回 1 つの質問をしてください。同一の行は同じ事実ですか、それとも別の事実ですか?別々の場合、または重複できない場合はUNION ALLを使用してください。一意のリストが必要な場合は、UNION を使用してください。自分のレポートを確認するには、SUM または COUNT の近くにある UNION をコードで検索し、それらの合計が本当に正しいことを確認します。
よくある質問
UNION と UNION ALL の違いは何ですか?
UNION は 2 つの結果セットを結合し、重複する行を削除します。 UNION ALL はそれらを結合し、重複を含むすべての行を保持します。
UNION と UNION ALL ではどちらが速いですか?
UNION ALL は重複をチェックしないため、通常、計算コストが低くなります。私たちのテストが示したように、はるかに大きな結果を返すには、全体的にさらに時間がかかる可能性があります。
UNION は 1 つのテーブル内の重複を削除しますか?
はい。すべて同じテーブルから取得された同一の行を含め、結合結果全体から重複を削除します。
UNION では列名が一致する必要がありますか?
いいえ。列は位置によって照合され、結果には最初の SELECT の名前が使用されます。列数が一致し、型に互換性がある必要があります。
UNION で ORDER BY を使用できますか?
はい、ただしステートメントの最後に ORDER BY を 1 つ置きます。単一のブランチではなく、結合された結果全体をソートします。
学び続ける
テスト、WordPress、または SEO についてサポートが必要ですか?
私たちは、チームがより優れたソフトウェアを出荷し、サイトを成長させるのを支援します。あなたが取り組んでいることを教えてください。明確な次のステップを提案します。
詳しいガイドはこちら テスト、AI、最新の開発
この記事は気に入りましたか?トピックを選択して、最新のチュートリアルに直接アクセスしてください。
AI 幻覚の説明: 言語モデルが物事をでっち上げる理由とそれを軽減する方法
AI 幻覚について説明しました。幻覚とは何か、言語モデルが幻覚を生成する理由、一般的な種類、グラウンディングとプロンプトで幻覚を軽減する方法、そして私たちが実行した簡単なチェックです。
記事を読む →DevOps環境変数の説明: .env ファイル、シークレット、および設定が正しく行われている
実行した Python の例を使用して環境変数について説明します。環境変数の読み取りと設定、すべての値が文字列である理由、.env ファイル、プロセスの継承、シークレット、検証について説明します。
記事を読む →ソフトウェア開発API レート制限の説明: アルゴリズム、ヘッダー、および 429 エラーの処理
API レート制限については、実行したシミュレーションで説明します。トークン バケット、固定ウィンドウ、スライディング ウィンドウ、429 応答、レート制限ヘッダー、バックオフによる再試行、およびテスト制限です。
記事を読む →テスト自動化Python でのモッキング:unittest.mock、patch、およびテストを嘘にする間違い
Python でのunittest.mockによるモック、テスト済み: モックとreturn_value、side_effect、名前が使用されている場所のパッチ、仕様と自動仕様、日付のモック、およびよくある間違い。
記事を読む →ソフトウェアテストコードカバレッジの説明: 回線カバレッジとブランチカバレッジ、および 100% の実際の意味
実際のcoverage.pyの実行でコードカバレッジを説明: 行、分岐、条件のカバレッジ、レポートの読み取り、100%のカバレッジでもバグを見逃す可能性がある理由、および賢明なターゲット。
記事を読む →データベースとSQLSQL における DELETE、TRUNCATE、DROP: 違い、ロールバック、およびそれぞれをいつ使用するか
DELETE、TRUNCATE、DROP について、テスト済み SQL を使用して説明します。それぞれの削除内容、ロールバック、トリガー、ID リセット、速度、PostgreSQL、MySQL、SQL Server、SQLite の違いについて説明します。
記事を読む →データベースとSQLSQL ビューの説明: 作成、使用、落とし穴の回避、例を示します
SQL ビューについて、実行したクエリとともに説明しました。ビューの作成、ライブ結果、列の非表示、パフォーマンス、更新可能なビューと具体化されたビュー、壊れた依存関係、ベスト プラクティスについて説明します。
記事を読む →ソフトウェア開発TypeScript インターフェイスと型: 実際の違い、コンパイラでテスト
TypeScript インターフェイスと型、実際のコンパイラでチェック: 両方でできること、片方だけでできること、宣言のマージ、拡張と交差、および従うべき簡単なルール。
記事を読む →ソフトウェア開発Python *args と **kwargs の説明: 柔軟な関数と明確な例
Python の *args と **kwargs について、実行したコードで説明しました。パッキングとアンパッキング、パラメーターの順序、キーワードのみの引数と位置のみの引数、デコレーター、一般的なエラーです。
記事を読む →ソフトウェア開発Python Lambda 関数: 構文、実際の用途、および使用すべきでない場合
Python のラムダ関数について、実行したコードとともに説明します。構文、キーによるソート、マップとフィルター、クロージャー、遅延バインディング トラップ、通常の def がより適切な選択である場合。
記事を読む →人工知能AIエージェントとは何ですか?シンプルなエージェント ループを実行できる仕組み
AIエージェントとは何ですか?エージェント ループ、ツール、メモリ、ガードレール、実行した小さな Python ループ、実際のリスク、およびシンプルなチャットボットがより良い選択である場合についてのわかりやすいガイドです。
記事を読む →DevOpsモニタリングと可観測性: ログ、メトリクス、トレースによる本当の違い
モニタリングと可観測性について説明: 既知および未知の障害、ログ、メトリクスとトレース、チェックアウト インシデントのウォークスルー、ゴールデン シグナル、OpenTelemetry、および便利なアラート。
記事を読む →DevOpsDocker ボリュームとバインド マウント: コンテナ データを正しい方法で保持する
Docker ボリュームとバインド マウントについて説明します。コンテナ データが消える理由、名前付きボリューム、バインド マウント、tmpfs、Compose の例、バックアップ、アクセス許可、およびそれぞれをいつ使用するかについて説明します。
記事を読む →テスト自動化TDD と BDD: 主な違い、1 つの機能が両方の方法で構築され、それぞれをいつ使用するか
TDD と BDD は、両方の方法で構築された 1 つの割引機能で説明されています。実行したコードによるレッド-グリーン-リファクタリング、Given-When-Then シナリオ、ツール、トレードオフ、およびそれぞれをいつ使用するかです。
記事を読む →ソフトウェアテストユーザー受け入れテスト (UAT): プロセス、チェックリスト、および実際の例
ユーザー受け入れテストの説明: 誰が実行するか、QA との違い、7 段階のプロセス、UAT テスト ケース テンプレート、チェックリスト、サインオフ基準、およびよくある間違い。
記事を読む →データベースとSQLSQL NULL 値の説明: IS NULL、COALESCE、NULLIF、および回避すべきトラップ
SQL の NULL 値について、実行したクエリで説明しました。3 つの値のロジック、IS NULL、COALESCE、NULLIF、集計、結合、並べ替えでの NULL の扱い方、およびそれが密かに引き起こすバグです。
記事を読む →データベースとSQLSQL CASE WHEN ステートメント: 構文、実際の例、およびよくある間違い
SQL CASE WHEN では、単純な検索フォーム、条件順序、SUM を使用したピボット、COUNT トリック、カスタム並べ替え、更新、回避すべき NULL トラップなど、実行したクエリを使用して説明しました。
記事を読む →ソフトウェア開発JWTとは何ですか? JSON Web トークンを実際の例で説明する
JWTとは何ですか? JSON Web トークンについて説明しました。3 つの部分、実行したコード内で構築および改ざんされたトークン、JWT とセッション、ストレージ、リフレッシュ トークン、およびセキュリティ上の間違いです。
記事を読む →ソフトウェア開発JavaScript イベントループの説明: コールスタック、マイクロタスク、タイマーと例
JavaScript イベント ループについて、実行したコードで説明しました。コール スタック、タスク キュー、マイクロタスク キュー、setTimeout 0 が即時ではない理由、ブロッキング、スターベーション、およびインタビュー クイズです。
記事を読む →ソフトウェア開発Python ジェネレーターと収量の説明: 実際の例でメモリを節約する
Python ジェネレーターと Yield について、実行したコードを使用して説明します。一時停止と再開の方法、メモリ節約の測定、パイプライン、無限シーケンス、Yield from、send、および一般的なトラップについて説明します。
記事を読む →人工知能埋め込みとは何ですか?ベクトルとコサインの類似度を簡単に説明
埋め込みとは何ですか?ベクトル、コサイン類似度、セマンティック検索に関する平易なガイド。私たちが実行した小さな例、一般的な使用法、モデルの選択、既知の制限が含まれています。
記事を読む →DevOpsBlue-Green デプロイメントと Canary デプロイメント: 違い、トレードオフ、および選択方法
ブルー グリーン デプロイメントとカナリア デプロイメントについて説明: それぞれの仕組み、コスト、リスクとロールバック、テストした安定したユーザー バケット化、データベース移行、ローリング アップデート、および選択方法。
記事を読む →テスト自動化不安定なテスト: 問題の原因とそれを永久に修正する方法
不安定なテストについては、私たちが実行したデモを使用して説明しました。主な原因、確認および診断する方法、タイミングの適切な修正、共有された状態と日付、隔離プロセスなどです。
記事を読む →ソフトウェアテスト負荷テストとストレス テスト: 違い、メトリクス、および k6 の例
ロード テストとストレス テストについて説明します。それぞれが何を証明するか、スパイク テストとソーク テスト、重要な指標、平均値が誤解を招く理由、K6 の例、テストの計画方法について説明します。
記事を読む →ソフトウェアテストテスト ケースとテスト シナリオ: 主な違い、例、およびそれぞれをいつ使用するか
テスト ケースとテスト シナリオの説明: 明確な定義、並べて表、シナリオからケースへの 1 つのパスワード リセット機能、テンプレート、およびそれぞれをいつ使用するか。
記事を読む →データベースとSQLSQL クエリの最適化: 実行プランを読み取り、タイミングを考慮して遅いクエリを修正
SQL クエリの最適化は 100 万行でテストされています。実行プランの読み取り、適切なインデックスの追加、検索対象外のフィルターの修正、複合インデックスとキーセットのページネーションの使用。
記事を読む →データベースとSQLSQL UNION と UNION ALL: 違い、例、テストされたパフォーマンス
SQL UNION と UNION ALL について、実行したクエリで説明しました。重複、両方に従うルール、実際のデータのバグ、測定されたパフォーマンス、INTERSECT と EXCEPT、およびそれぞれをいつ使用するかについて説明します。
記事を読む →ソフトウェア開発JavaScript Fetch API チュートリアル: GET、POST、エラー処理、タイムアウト
ローカル サーバーに対してテストされた JavaScript Fetch API チュートリアル: GET と POST、404 がスローされない理由、再利用可能なヘルパー、クエリ文字列、タイムアウト、CORS、およびよくある間違い。
記事を読む →ソフトウェア開発Python ファイル処理: 読み取り、書き込み、CSV、JSON、パスライブラリと例
Python のファイル処理について、実行したコードで説明します。オープン モード、大きいファイルの読み取り、CSV、JSON、パスライブラリ、バイナリ ファイル、安全な書き込み、エラー処理、およびよくある間違いについて説明します。
記事を読む →ソフトウェア開発Python のクラスとオブジェクト: 実際の例を含む OOP チュートリアル
Python のクラスとオブジェクトについて、実行したコードとともに説明します: __init__、メソッド、クラスとインスタンスの属性、継承、プロパティ、ダンダー メソッド、データクラス、およびよくある間違い。
記事を読む →人工知能大規模言語モデルとは何ですか? LLM の仕組みを誇大広告なしで説明
大規模言語モデルとは何ですか? LLM は、トークン、エンベディング、アテンション、トレーニング、温度およびコンテキスト ウィンドウ、小さな次の単語のデモ、実際の制限など、平易な言葉で説明されています。
記事を読む →DevOps初心者のための Linux コマンド: 例を含む基本ターミナル ガイド
初心者向けの Linux コマンド。ナビゲーション、ファイル、ログの表示、grep、パイプ、権限、プロセス、アーカイブなどのタスク別にグループ化されており、実用的なログ分析の例も含まれています。
記事を読む →テスト自動化Selenium と Playwright: 主な違い、コードの比較、どちらを選択するか
Selenium と Playwright の比較: アーキテクチャ、待機、ブラウザと言語のサポート、デバッグ、両方のツールでの同じテスト、移行のアドバイスと選択方法。
記事を読む →ソフトウェアテスト等価性分割: テスト設計手法を実際の例で説明
等価性パーティション化について説明しました。有効なパーティションと無効なパーティションを見つける方法、年齢、パスワード、クーポンに関する実際の例、実行したテスト、境界と組み合わせる理由。
記事を読む →ソフトウェアテストソフトウェアテストにおける重大度と優先度: 相違点、マトリックス、および実際の例
ソフトウェア テストにおける重大度と優先度について説明します。明確な定義、例を含む 4 方向のマトリックス、レベル スケール、それぞれの設定者、バグ トリアージの実行方法。
記事を読む →データベースとSQLSQL サブクエリのチュートリアル: 型、相関サブクエリ、および EXISTS と例
実行したクエリを含む SQL サブクエリのチュートリアル: スカラー、IN、FROM、SELECT サブクエリ、相関サブクエリ、EXISTS、NOT IN NULL トラップ、サブクエリ対 JOIN 対 CTE。
記事を読む →データベースとSQLSQL トランザクションと ACID の説明: COMMIT、ROLLBACK、分離レベル
SQL トランザクションと ACID について、実行した銀行振込で説明しました。COMMIT、ROLLBACK、セーブポイント、ロック、分離レベル、ダーティ リード、デッドロック、ベスト プラクティスについて説明します。
記事を読む →ソフトウェア開発Git mergeとrebaseの違い:例と使い分け
Git mergeとrebaseの違いを、実際のログ出力、比較表、rebaseの黄金律、安全なチームワークフローで解説します。
記事を読む →ソフトウェア開発Pythonのリスト内包表記:構文・例・使うべきでない場面
Pythonのリスト内包表記を解説:構文、フィルタ、if-else、ネストしたループ、実測した処理時間、そして通常のforループの方が良い場面。
記事を読む →データベースとSQLSQL JOINを例で解説(Inner・Left・Right・Full)
サンプルのテーブルとクエリでSQL JOINを順に解説。INNER、LEFT、RIGHT、FULL、CROSS、SELFに加え、よくある間違いとパフォーマンスのコツも紹介します。
記事を読む →