質問

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

SELECT c FROM myTbl GROUP BY C

次と同じ結果があります:

SELECT DISTINCT C FROM myTbl

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

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

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

役に立ちましたか?

解決

MusiGenesis 'の応答は機能的に述べられているあなたの質問に関して正しいもの; SQL Serverは、「グループ化」を使用している場合、集計関数を使用しない場合、実際に意味するのは「個別」です-したがって、単純に" Distinct。""

を使用したかのように実行計画を生成します。

ただし、メモに注意することが重要だと思いますの対応-「Group By」の無頓着な扱いおよび「個別」注意しないと、悪意のある落とし穴が発生する可能性があります。これが「集計に関する質問ではない」と言うのは完全に正しいわけではありません。というのは、2つのSQLクエリキーワードの機能の違いについて尋ねているからです。1つは集計で使用する意味、もう1つはそうではありません。

ハンマーは時々ネジを打ち込むことができますが、ドライバーが手元にある場合は、なぜ気にしますか?

(この類推のために、 Hammer:Screwdriver :: GroupBy:Distinct および screw =>テーブル列の一意の値のリストを取得

他のヒント

GROUP BY では、 AVG MAX MIN SUMなどの集約関数を使用できます、および COUNT 。 一方、 DISTINCT は重複を削除するだけです。

たとえば、大量の購入記録があり、各部門がどれだけの費用を費やしたかを知りたい場合、次のようにします。

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

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

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

http://sqlmag.com/database-performance-tuning/distinct-対グループ

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

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

重複を削除するだけの場合は、 DISTINCT を使用します。集約演算子( MAX SUM GROUP_CONCAT 、...、またはを適用する場合は、 GROUPY BY を使用します HAVING 句)。

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

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

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

  • FROM JOIN APPLY などを含む)
  • WHERE
  • GROUP BY (重複を削除できます)
  • 集計
  • HAVING
  • ウィンドウ関数
  • SELECT
  • DISTINCT (重複を削除できます)
  • UNION INTERSECT EXCEPT (重複を削除できます)
  • 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

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

実行に微妙な違いが生じる可能性があると思います。 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" vs.「HASH UNIQUE」。ただし、推定コストなどは同じです。その後、トレースをオンにしてこれらを実行しましたが、実際の操作カウントは両方で同じでした(ただし、2番目の操作カウントはキャッシュのために物理的な読み取りを行う必要はありませんでした)。

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

この目的にはDISTINCT構文を好むと思います。これは単なる習慣ではなく、クエリの目的をより明確に示しています。

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

たとえば、次とは異なります

SELECT C FROM myTbl GROUP BY C, D

上記のすべてのコメントを読みましたが、集約ビットを除き、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行を返します。

理由は上記で述べたとおりで、異なる動作をすることができます!

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

特定のデータで結果が同等であっても、セマンティクスは異なります。

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

DISTINCTを意味する場合、たとえ同じように機能する場合でも、GROUP BYを使用しないでください。クエリのミリ秒を削減しようとしていると仮定していますが、開発者の時間はコンピューターの時間よりも桁違いに高いことを指摘する必要があります。

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

ただし、GROUP BYの目的は集計を達成することであるため、DISTINCT句を使用して一意のレコードを検索する方が適切です。

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

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

明確なのは、そのように聞こえます-一意の行を取得します。

SQL Server 2005では、クエリオプティマイザーが、実行した単純な例の違いを最適化することができるようです。ダンノ、もしあなたがすべての状況でそれを当てにできるなら。

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

「SQL the language」の観点から見ると、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;

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を使用する可能性が高くなります。

あなたが気づいているのは、単一の列を選択しているからです。

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

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

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

各個人のすべてのトランザクションの合計が表示されます。

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

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

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

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

i.e:

select distinct a, b, c from table;

と同じ:

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

機能効率はまったく異なります。 「戻り値」のみを選択する場合は、重複するものを除いて、個別に使用する方がグループ化するよりも優れています。 「グループ化」の理由include(ソート+削除)、" distinct&quot ;;含める(削除する)

Hive(HQL)では、group byは個別よりもはるかに高速です。前者はテーブル内のすべてのフィールドを比較する必要がないためです。 https://sqlperformance.com/2017を参照してください。 / 01 / t-sql-queries / surprises-asssumptions-group-by-distinct

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

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

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

@tmpresultに挿入 5を選択 ユニオンオール 2を選択 ユニオンオール 3を選択 ユニオンオール 4を選択

個別に選択 Id @tmpresultから

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top