396

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

SELECT c FROM myTbl GROUP BY C

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

SELECT DISTINCT C FROM myTbl

私が興味を持っているのは、SQL エンジンがコマンドを処理する方法に何か違いがあるのですか、それとも本当に同じことですか?

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

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

4

26 に答える 26

290

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

ただし、 Hankの応答にも注意することが重要だと思います。「Group By」と「Distinct」の無頓着な扱いは、注意を怠ると、後でいくつかの有害な落とし穴につながる可能性があります。これが「集計に関する質問ではない」と言うのは完全に正しくありません。なぜなら、2 つの SQL クエリ キーワードの機能上の違いについて質問しているためです。

ハンマーを使ってネジを打ち込むこともありますが、ドライバーが手元にあるのであれば、わざわざする必要はありません。

(この類推の目的で、Hammer : Screwdriver :: GroupBy : Distinctおよびscrew => get list of unique values in a table column)

于 2008-10-02T20:52:47.033 に答える
167

GROUP BYAVGMAXMINSUM、などの集計関数を使用できますCOUNT。一方、DISTINCT重複を削除するだけです。

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

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

これにより、部門ごとに 1 つの行が得られます。これには、部門名と、amountその部門のすべての行のすべての値の合計が含まれます。

于 2008-10-02T20:10:58.163 に答える
68

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

とは異なり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

このトピックについては、ブログ記事で詳しく説明しています

于 2017-08-23T07:43:13.443 に答える
50

違いはありません(少なくとも 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

于 2008-10-02T20:41:02.973 に答える
35

DISTINCT重複を削除したい場合に使用します。集計演算子 ( 、、、 ...、または句)GROUPY BYを適用する場合に使用します。MAXSUMGROUP_CONCATHAVING

于 2008-10-02T20:11:07.973 に答える
20

それらの実行には微妙な違いがある可能性があると思います。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 構文を使用する必要があると思います。これは単なる習慣ではなく、クエリの目的をより明確に示します。

于 2008-10-02T20:51:01.920 に答える
14

投稿したクエリの場合、それらは同一です。しかし、そうでない可能性がある他のクエリについては。

たとえば、次と同じではありません。

SELECT C FROM myTbl GROUP BY C, D
于 2008-10-02T20:11:37.177 に答える
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 行を返します。

その理由は、上で述べたように、動作が異なる可能性があるためです。

于 2012-05-17T16:04:57.037 に答える
11

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

于 2008-10-02T20:12:00.280 に答える
7

GROUP BY には、DISTINCT 関数とは異なる (へー) 非常に具体的な意味があります。

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 を使用します。これにより、データベースはニーズに合わせてクエリを最適化できます。

于 2008-10-02T20:20:31.277 に答える
6

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

ただし、GROUP BY の目的は集約を達成することであるため、DISTINCT 句が提供されている場合は、一意のレコードを見つけるためにそれを使用することをお勧めします。

于 2011-12-28T11:28:58.283 に答える
6

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

于 2008-10-02T20:10:10.707 に答える
5

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

于 2008-10-02T20:57:40.750 に答える
4

group by は集計操作で使用されます。たとえば、列 C で分類された B の数を取得する場合などです。

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

一意の行が得られます。

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

于 2008-10-02T20:15:29.867 に答える
3

その特定のクエリでは違いはありません。ただし、もちろん、集計列を追加する場合は、group by を使用する必要があります。

于 2008-10-02T20:12:44.397 に答える
2

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

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

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

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

SELECT COUNT(DISTINCT C) FROM myTbl;

SELECT DISTINCT COUNT(C) FROM myTbl;
于 2008-10-03T10:09:12.443 に答える
2

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

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

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

于 2016-01-29T16:06:26.983 に答える
1

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

2 つのフィールドを選択してみて、どうなるか見てみましょう。

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

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

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

于 2008-10-02T20:16:27.383 に答える
0

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

すなわち:

select distinct a, b, c from table;

以下と同じです:

select a, b, c from table group by a, b, c
于 2008-10-02T21:05:41.370 に答える
-1

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

簡単な例を試す

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

@tmpresult に挿入 選択 5 すべて結合 選択 2 すべて結合 選択 3 すべて結合 選択 4

@tmpresult から個別の ID を選択

于 2015-02-10T16:56:21.003 に答える