GROUP BYとDISTINCTの間に違いはありますか


310

先日、SQLについて簡単なことを学びました。

SELECT c FROM myTbl GROUP BY C

次と同じ結果になります。

SELECT DISTINCT C FROM myTbl

私が知りたいのは、SQLエンジンがコマンドを処理する方法に何か違いはありますか、それともまったく同じですか?

私は個人的には明確な構文を好みますが、他の何よりも習慣から外れていると確信しています。

編集:これは、集計に関する問題ではありません。GROUP BY集計関数での使用が理解されています。


11
これは集計についての質問ではありません。集計関数が存在しない場合、それは
DISTINCT

2
またSELECT c FROM myTbl UNION SELECT c FROM myTbl、同じ結果を取得して取得することもできます...しかし、SELECT DISTINCTが非常に簡単なのになぜ複雑なのか。
jarlh 2017

の「実行の論理順序」はGROUP BY「SELECT」よりはるかに早く、DISTINCTselectに従います。
Used_By_Already

私が言及していない非常に小さな違いの1つはDISTINCT、実際にフィールドを選択する結果になることです。つまり、値が結果セットに表示されます。GROUP BY実際にフィールドを選択しなくても、重複を効果的に削除できます。これはほとんどの場合多少関係ありませんが、他の場合はまさにあなたが望むものである可能性があります。最終的GROUP BYにの代わりに使用する場合DISTINCTは、コード内の説明コメントがおそらく正当化されます。
rinogo

結論としては、重複削除は実行プランの異なるポイントで発生するため、重複削除ではソートまたはこのインデックスを使用する必要があるため、一方が他方よりも効率的になる可能性があるようです。したがって、初期の重複除去の利点があるか、または行数が少なくソートが無視できる場合に、早い段階で別のインデックスを使用し、後でソートを実行することで利点が得られる可能性があります。
bielawski

回答:


246

MusiGenesisの応答は、述べられているように、機能的にあなたの質問に関して正しいものです。SQL Serverは、 "Group By"を使用し、集計関数を使用していない場合、実際に意味するのは "Distinct"であることを認識できるほどスマートです。したがって、単に "Distinct"を使用したかのように実行プランを生成します。 」

ただし、ハンクの応答にも注意することが重要だと思います。「Group By」と「Distinct」を無頓着に扱うと、慎重に行かないと厄介な問題が発生する可能性があります。2つのSQLクエリキーワードの機能の違いについて質問しているので、これは「集計についての質問ではない」と言うのは完全に正しくありません。1つは集計で使用するためのもので、もう1つはそうではありません。

ハンマーは時々ねじで打ち込むように働くことができます、しかしあなたが便利なドライバーを持っているなら、なぜ面倒ですか?

(この類似の目的のために、Hammer : Screwdriver :: GroupBy : Distinctそしてscrew => get list of unique values in a table column


私はあなたとSkeolanに完全に同意します。この機能に出くわしたとき、とても驚きました。それは私が使うつもりはありませんが、私が働いているこの新しい場所で物事が行われた方法です。
Brettski、2008年

少なくともOracle 12では、DISTINCT、UNIONによる個別の値の取得、GROUP BYの動作が異なる場合があるようです。今日の初めに、DISTINCTとDISTINCT BY DISINCTがOracleエラーを引き起こすケースがありましたが、GROUP BYは機能しました。ビューから列を1つだけ選択し、集計を使用していませんでした。なぜそれが必要なのかはまだわかりませんが、実行に多少の違いがあることは確かです。他の人が指摘しているように、selectに含まれていないGROUP BY列を使用することもできますが、集計なしではほとんど必要ありません。
ZeroK

1
SQLに関しては、ドライバーとハンマーの両方を常に使用できます。なぜハンマーを使用してねじを打ち込むのですか?
jarlh

アナロジーについて明確にするために-この場合、ハンマー== GroupByとドライバー==は区別されますか?
HopeKing 2018

わあ、この10年前の質問にはまだ足があります。「固有値のリスト」がねじの場合、「別個」はドライバーです。アナロジーをより明確にするために、答えを更新します。
Skeolan 2018

136

GROUP BY以下のように、あなたは、集計関数を使用することができますAVGMAXMINSUM、とCOUNT。一方、DISTINCT重複を削除するだけです。

たとえば、大量の購入記録があり、各部門で費やされた金額を知りたい場合は、次のようにします。

SELECT department, SUM(amount) FROM purchases GROUP BY department

これにより、部門ごとに1行が表示され、部門名と、amountその部門のすべての行のすべての値の合計が含まれます。


2
GROUP BYの使用は理解しています。質問は、集約関数が存在しない場合に別個のデータセットを返すという事実に基づいています。
Brettski、2008年

2
GROUP BYは、グループ化している列の値に対して暗黙的にDISTINCTを実行するためです(不協和音のため申し訳ありません)。
ジョーピネダ

DISTINCT+集約関数を使用することはできませんか?このように:select distinct department, SUM(amount) from ...
Shafizadeh 2015

@Sajad、あなたはそうすることができますが、それでもGROUP BYが必要なので、DISTINCTは何もしません。
ZeroK

44

違いはありません(少なくともSQL Serverでは)。どちらのクエリも同じ実行プランを使用します。

http://sqlmag.com/database-performance-tuning/distinct-vs-group

サブクエリが含まれている場合、おそらく違いがあります。

http://blog.sqlauthority.com/2007/03/29/sql-server-difference-between-distinct-and-group-by-distinct-vs-group-by/

違いはありません(Oracleスタイル):

http://asktom.oracle.com/pls/asktom/f?p=100:11:0::::P11_QUESTION_ID:32961403234212


40

単なる重複削除機能の観点からの違いは何ですか

とは異なりDISTINCTグループごとにGROUP BYデータを集約できるという事実(他の多くの回答で言及されている)とは別に、私の意見で最も重要な違いは、2つの操作が論理順序の 2つの非常に異なるステップで「発生」するという事実ですステートメントで実行される操作の数SELECT

最も重要な操作は次のとおりです。

  • FROM(含むJOINAPPLY等)
  • WHERE
  • GROUP BY (重複を削除できます)
  • 集計
  • HAVING
  • ウィンドウ関数
  • SELECT
  • DISTINCT (重複を削除できます)
  • UNIONINTERSECTEXCEPT (重複を除去することができます)
  • ORDER BY
  • OFFSET
  • LIMIT

ご覧のとおり、各操作の論理的な順序は、その操作で実行できる内容と、後続の操作にどのように影響するかに影響を与えます。特に、事実は、GROUP BY動作は、「前に発生」SELECT操作(投影)を意味します:

  1. 投影に依存しません(これは利点になる可能性があります)
  2. 投影からの値は使用できません(これは不利になる場合があります)

1.投影に依存しない

プロジェクションに依存しないことが役立つ例は、個別の値でウィンドウ関数を計算する場合です。

SELECT rating, row_number() OVER (ORDER BY rating) AS rn
FROM film
GROUP BY rating

Sakilaデータベースに対して実行すると、次のようになります

rating   rn
-----------
G        1
NC-17    2
PG       3
PG-13    4
R        5

同じことはDISTINCT簡単には達成できませんでした:

SELECT DISTINCT rating, row_number() OVER (ORDER BY rating) AS rn
FROM film

このクエリは「間違っている」ため、次のような結果になります。

rating   rn
------------
G        1
G        2
G        3
...
G        178
NC-17    179
NC-17    180
...

これは私たちが望んでいたことではありません。DISTINCT操作は「後に起こりません」我々はもはや取り除くことができるように、投影DISTINCT窓関数がすでに計算され、投影されたため、評価を。を使用するDISTINCTには、クエリのその部分をネストする必要があります。

SELECT rating, row_number() OVER (ORDER BY rating) AS rn
FROM (
  SELECT DISTINCT rating FROM film
) f

補足:この特定のケースでは、DENSE_RANK()

SELECT DISTINCT rating, dense_rank() OVER (ORDER BY rating) AS rn
FROM film

2.投影からの値は使用できません

SQLの欠点の1つは、時々その冗長性です。これまでに見たのと同じ理由(つまり、操作の論理的な順序)のため、投影しているものを「簡単に」グループ化することはできません。

これは無効なSQLです:

SELECT first_name || ' ' || last_name AS name
FROM customer
GROUP BY name

これは有効です(式を繰り返します)

SELECT first_name || ' ' || last_name AS name
FROM customer
GROUP BY first_name || ' ' || last_name

これも有効です(式をネストします)

SELECT name
FROM (
  SELECT first_name || ' ' || last_name AS name
  FROM customer
) c
GROUP BY name

このトピックについてブログの投稿で詳しく説明しました


正直に言って、この質問では執行の順番がすぐには議論されなかったことに驚きました。ありがとうございます。あなたの点2.いくつか(1つ?)のデータベースでは、クエリ全体で選択エイリアスを使用できます(私が知っているのはTeradataですが、例外です)。
Used_By_Already 2017年

@Used_By_Already:もちろん、一部のデータベースはそれを行っています。多くのデータベースでは、これらのエイリアスを部分的にのみ使用できます(たとえば、そうではないWHEREかもしれませんGROUP BY)。いずれにせよ、それは悪い考えだと思います。移植性やメンテナンス上の理由から、この機能を使用しないことをお勧めします。「突然」、たとえば集計関数やウィンドウ関数のエイリアスを作成するときに機能しなくなります。
Lukas Eder

never using that feature for portability and maintenance reasons!! 100%同意しました...&ブログも楽しんでいます。すばらしい仕事です。乾杯。
Used_By_Already

32

DISTINCT重複を削除したいだけの場合に使用します。使用GROUPY BYあなたが集計演算子を適用する場合(MAXSUMGROUP_CONCAT、...、またはHAVING句)。


19

それらの実行には微妙な違いがある可能性があると思います。Oracle 10gでこれらの行に沿って機能的に同等な2つのクエリの実行プランを確認しました。

core> select sta from zip group by sta;

---------------------------------------------------------------------------
| Id  | Operation          | Name | Rows  | Bytes | Cost (%CPU)| Time     |
---------------------------------------------------------------------------
|   0 | SELECT STATEMENT   |      |    58 |   174 |    44  (19)| 00:00:01 |
|   1 |  HASH GROUP BY     |      |    58 |   174 |    44  (19)| 00:00:01 |
|   2 |   TABLE ACCESS FULL| ZIP  | 42303 |   123K|    38   (6)| 00:00:01 |
---------------------------------------------------------------------------

core> select distinct sta from zip;

---------------------------------------------------------------------------
| Id  | Operation          | Name | Rows  | Bytes | Cost (%CPU)| Time     |
---------------------------------------------------------------------------
|   0 | SELECT STATEMENT   |      |    58 |   174 |    44  (19)| 00:00:01 |
|   1 |  HASH UNIQUE       |      |    58 |   174 |    44  (19)| 00:00:01 |
|   2 |   TABLE ACCESS FULL| ZIP  | 42303 |   123K|    38   (6)| 00:00:01 |
---------------------------------------------------------------------------

中間の操作は少し異なります。「HASH GROUP BY」と「HASH UNIQUE」ですが、推定コストなどは同じです。次に、トレースをオンにしてこれらを実行しましたが、実際の操作数は両方で同じでした(ただし、2番目の操作では、キャッシュのために物理的な読み取りを行う必要がありませんでした)。

しかし、操作名が異なるため、実行は多少異なるコードパスをたどり、より大きな違いの可能性が開かれると思います。

この目的にはDISTINCT構文を使用することをお勧めします。これは単なる習慣ではなく、クエリの目的をより明確に示します。


14

投稿したクエリの場合、それらは同じです。しかし、正しくない可能性のある他のクエリの場合。

たとえば、以下とは異なります。

SELECT C FROM myTbl GROUP BY C, D

14

上記のコメントをすべて読みましたが、集約ビットを除いて、Group ByとDistinctの主な違いを指摘している人はいませんでした。

Distinctはすべての行を返し、それらを重複排除しますが、Group Byは、アルゴリズムによって1つずつ読み取られるときに行を重複排除します。

つまり、異なる結果が得られる可能性があります。

たとえば、以下のコードは異なる結果を生成します。

SELECT distinct ROW_NUMBER() OVER (ORDER BY Name), Name FROM NamesTable

 SELECT ROW_NUMBER() OVER (ORDER BY Name), Name FROM NamesTable
GROUP BY Name

テーブルに10個の名前があり、そのうちの1つが別の名前と重複している場合、最初のクエリは10行を返しますが、2番目のクエリは9行を返します。

理由は、私が上で言ったので、彼らは異なる行動をとることができます!


11
あなただけでグループ化している間だからですName2番目のクエリでは、distinctキーワードは列の両方に適用されName、あなたROW_NUMBER()の列select最初のクエリのWHERE句。2番目のクエリの最初の列でグループ化した場合、クエリは同じ結果を返します。

これは、の結果でorder of executionある(一般的な意味で)SQL句の FROM and ON (joins)WHEREGROUP BYHAVINGSELECTDISTINCTORDER BYLIMIT / OFFSET / TOP)(第2のクエリが名前はROW_NUMBERにより、後群によって数が低減されるように一列に適用され得一意の名前ごと。最初のクエリでは、distinctが適用される前にrow_number()が適用されます。row_number()関数の性質により、すべての行は一意の整数を取得するため、名前の値が繰り返されている場合でも、すべての行が返されます。
Used_By_Already

12

複数の列でDISTINCTを使用する場合、結果セットはGROUP BYの場合のようにグループ化されず、DISTINCTで集計関数を使用することはできません。


11

特定のデータで同等の結果が得られたとしても、セマンティクスは異なります。


6

GROUP BYは、DISTINCT関数とは異なる(heh)非常に特定の意味を持っています。

GROUP BYを使用すると、選択した式を使用してクエリ結果がグループ化され、集計関数を適用できます。これらは、結果セット全体ではなく、各グループに作用します。

役立つ例を次に示します。

次のようなテーブルがあるとします。

name
------
barry
dave
bill
dave
dave
barry
john

このクエリ:

SELECT name, count(*) AS count FROM table GROUP BY name;

このような出力を生成します:

name    count
-------------
barry   2
dave    3
bill    1
john    1

DISTINCTを使用する場合とは明らかに異なります。結果をグループ化する場合はGROUP BYを使用し、特定の列の一意のリストのみが必要な場合はDISTINCTを使用します。これにより、データベースがニーズに合わせてクエリを最適化する機会が与えられます。


6

DISTINCTを意味する場合は、たとえ同じように機能しても、GROUP BYを使用しないでください。私はあなたがクエリからミリ秒を節約しようとしていると仮定しています、そして私は開発者の時間がコンピュータの時間よりも桁違いに高価であることを指摘しなければなりません。


5

集約関数なしでGROUP BYを使用している場合、内部ではDISTINCTとして扱われるため、この場合、GROUP BYとDISTINCTの間に違いはありません。

ただし、DISTINCT句が提供されている場合、GROUP BYの目的は集計を達成することなので、一意のレコードを検索するために使用する方が適切です。


4

group byは集約操作で使用されます-列Bごとに分類されたBの数を取得する場合など

select C, count(B) from myTbl group by C

はっきりとは、それがどのように聞こえるかです-あなたはユニークな行を取得します。

SQL Server 2005では、クエリオプティマイザーが、実行した単純な例の違いを最適化できるように見えます。しかし、すべての状況でそれを当てにできる場合は、Dunnoです。



3

Teradataの観点では

結果セットの観点からは、TeradataでDISTINCTまたはGROUP BYを使用するかどうかは重要ではありません。回答セットは同じになります。

パフォーマンスの観点からは、同じではありません。

パフォーマンスに影響を与えるものを理解するには、DISTINCTまたはGROUP BYを使用してステートメントを実行したときにTeradataで何が起こるかを知る必要があります。

DISTINCTの場合、行は事前集計を行わずにすぐに再配分されますが、GROUP BYの場合、最初のステップで事前集計が行われ、その後、AMP全体で一意の値が再配分されます。

今では、GROUP BYが常にパフォーマンスの観点から優れているとは考えないでください。多くの異なる値がある場合、GROUP BYの事前集計ステップはあまり効率的ではありません。Teradataは、重複を削除するためにデータをソートする必要があります。この場合、最初に再配布するほうがよい場合があります。つまり、DISTINCTステートメントを使用します。重複する値が多数ある場合にのみ、再分散後に重複排除ステップが実行された後にのみGROUP BYステートメントを選択することをお勧めします。

つまり、TeradataでのDISTINCTとGROUP BYの意味は次のとおりです。

GROUP BY->多くの重複の場合DISTINCT->重複なし、または重複のみ。DISTINCTを使用すると、AMPのスプール領域が不足することがあります。その理由は、再配布がすぐに行われ、傾斜が原因でAMPのスペースが不足する可能性があるためです。

これが発生した場合、重複は最初のステップですでに削除されており、AMP間で移動されるデータが少ないため、GROUP BYを使用する可能性が高くなります。


なにTeradata
Brettski

Teradataはリレーショナルデータベース管理システム(RDBMS)であり、さまざまなクライアントプラットフォームから多数の同時ユーザーをサポートできます。TeradataはANSI標準と互換性があり、完全に並列アーキテクチャで構築されています。
Ram Ghadiyaram

2

「SQL言語」の観点から見ると、2つの構成要素は同等であり、どちらを選択するかは、私たち全員が行う必要がある「ライフスタイル」の選択の1つです。DISTINCTがより明示的である(したがって、コードを継承する人などにより配慮される)の良いケースがあると思いますが、それはGROUP BY構文が無効な選択であることを意味しません。

この「GROUP BYは集合体のためのもの」は強調が間違っていると思います。設定関数(MAX、MIN、COUNTなど)を省略できるため、コーダーの意図を理解できるようにする必要があります。

理想的なオプティマイザは同等のSQL構造を認識し、それに応じて常に理想的な計画を選択します。選択した実際のSQLエンジンについては、テストする必要があります:)

PSは、select句のDISTINCTキーワードの位置が異なる結果を生成する可能性があることに注意してください。

SELECT COUNT(DISTINCT C) FROM myTbl;

SELECT DISTINCT COUNT(C) FROM myTbl;

1

単一の列を選択しているので、それだけに気づいています。

2つのフィールドを選択して、何が起こるかを確認してください。

Group Byは次のように使用することを意図しています:

SELECT name, SUM(transaction) FROM myTbl GROUP BY name

これは、各個人のすべてのトランザクションの合計を示します。


これは集合体の問題ではありません。あなたの例では、SELECT c、d FROM mytbl GROUP BY C、D; 実際、SELECT DISTINCT C、D FROM mytblと同じデータセットを返します。これが質問の基本です
Brettski

1

私はそれが古い記事であることを知っています。しかし、ヒキガエルでそのクエリを使用しているときに個別の値を返すためにgroup byを使用するクエリがあり、Oracleはすべてが正常に機能したことを報告します。つまり、良好な応答時間です。Oracle 9iから11gに移行したとき、Toadでの応答時間は優れていましたが、以前のバージョンを使用した場合、レポートを完了するまでに約35分かかりました。

解決策は、グループを変更してDISTINCTを使用することでしたが、レポートは約30秒で実行されます。

これが同じ状況の人に役立つことを願っています。


1

使用法に関して、GROUP BYは、計算する行をグループ化するために使用されます。DISTINCTは計算を行いません。重複する行は表示されません。

重複せずにデータを表示したい場合は、常にDISTINCTを使用しました。

マンゴーの総量を合計するような計算をしたい場合は、GROUP BYを使用します


0

私が常に理解している方法は、distinctを使用することは、選択したすべてのフィールドを選択した順序でグループ化することと同じであることです。

つまり:

select distinct a, b, c from table;

と同じです:

select a, b, c from table group by a, b, c

同意しましたが、a、b、cによるテーブルグループからのc、b、aの選択と同じ
ですか

はい、同じです
Caius Jard 2018年

0

機能効率は全く異なります。重複するものを除いて「戻り値」のみを選択したい場合は、グループ化よりも区別を使用することをお勧めします。「グループ化」にはinclude(sorting + remove)が含まれるため、「distinct」にはinclude(remove)が含まれます



0

時々それらはあなたに同じ結果を与えるかもしれませんが、それらは異なる意味/ケースで使用されることを意図しています。主な違いは構文です。

以下の例に注意してください。DISTINCT重複する値のセットを除外するために使用されます。(6、cs、9.1)と(1、cs、5.5)は2つの異なるセットです。そうDISTINCTしながら、両方の行を表示するために起こっているGROUP BY Branch一組だけを表示するように起こっています。

 SELECT * FROM student; 
+------+--------+------+
| Id   | Branch | CGPA |
+------+--------+------+
|    3 | civil  |  7.2 |
|    2 | mech   |  6.3 |
|    6 | cs     |  9.1 |
|    4 | eee    |  8.2 |
|    1 | cs     |  5.5 |
+------+--------+------+
5 rows in set (0.001 sec)

SELECT DISTINCT * FROM student; 
+------+--------+------+
| Id   | Branch | CGPA |
+------+--------+------+
|    3 | civil  |  7.2 |
|    2 | mech   |  6.3 |
|    6 | cs     |  9.1 |
|    4 | eee    |  8.2 |
|    1 | cs     |  5.5 |
+------+--------+------+
5 rows in set (0.001 sec)

SELECT * FROM student GROUP BY Branch;
+------+--------+------+
| Id   | Branch | CGPA |
+------+--------+------+
|    3 | civil  |  7.2 |
|    6 | cs     |  9.1 |
|    4 | eee    |  8.2 |
|    2 | mech   |  6.3 |
+------+--------+------+
4 rows in set (0.001 sec)

GROUP BY節によって達成できる結果は、DISTINCT余分な節や条件を使用しないと達成できない場合があります。例えば上記の場合。

同じ結果を得るには、以下のようにDISTINCTすべての列名をGROUP BY句で渡す必要があります。構文の違いを見てください。GROUP BYその場合に句を使用するには、すべての列名についての知識が必要です。

SELECT * FROM student GROUP BY Id, Branch, CGPA;
+------+--------+------+
| Id   | Branch | CGPA |
+------+--------+------+
|    1 | cs     |  5.5 |
|    2 | mech   |  6.3 |
|    3 | civil  |  7.2 |
|    4 | eee    |  8.2 |
|    6 | cs     |  9.1 |
+------+--------+------+

またGROUP BY、デフォルトでDISTINCTは昇順で結果を表示しますが、表示しません。しかし、これについてはよくわかりません。ベンダーごとに異なる場合があります。

ソース:https : //dbjpanda.me/dbms/languages/sql/sql-syntax-with-examples#group-by


0

通常DISTINCT、表の特定の列の重複を排除するために使用できます。

「GROUP BY」のケースでは、などの集計関数を適用することができ AVGMAXMINSUM、およびCOUNT特定の列に、列名を取得し、それと同じ列に集計関数の結果。

例:

select  specialColumn,sum(specialColumn) from yourTableName group by specialColumn;

-1

集合関数の使用を除いて、group by句とdistinct句の間に大きな違いはありません。どちらも値を区別するために使用できますが、パフォーマンスの観点では、グループ化の方が適しています。個別のキーワードが使用されている場合、内部的には実行計画で表示できるソート操作が使用されていました。

簡単な例を試してください

@tmpresultテーブルを宣言します(Id tinyint)

@tmpresultに挿入選択5ユニオンすべて選択2ユニオンすべて選択3ユニオンすべて選択4

@tmpresultから個別のIDを選択します


明確で、両方の意志でグループ化
vignesh '30 / 12/30
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.