web-dev-qa-db-ja.com

クエリで個別に使用する必要があります

私が働いているところでは、最近、クエリでdistinctを使用することは、プログラマーの悪い兆候であると言われました。したがって、この関数を使用しない唯一の方法は、group byを使用することだと思います。

個別の関数は、その読み取り方法を除いて、グループと非常によく似ていると理解していました。個別の機能は、個々の選択基準と、全体としてのみ同じことを行うグループをチェックします。

私がするのはレポートだけだということを覚えておいてください。私はデータを作成/変更しません。したがって、私の質問は、個別またはグループ化を使用する必要がある場合のベストプラクティスについてです。どちらでもない場合、代替手段はありません。たぶん、group byは、ここでの私の非現実的な例よりも複雑なクエリで使用する必要がありますが、あなたはその考えを理解しています。クエリでdistinctを使用する必要がある理由または理由を実際に説明する回答が見つかりませんでした

select distinct
    spriden_user_id as "ID",
    spriden_last_name as "last",
    spriden_first_name as "first",
    spriden_mi_name as "MI",
    spraddr_street_line1 as "Street",
    spraddr_street_line2 as "Street2",
    spraddr_city as "city",
    spraddr_stat_code as "State",
    spraddr_Zip as "Zip"
from spriden, spraddr
where spriden_user_id = spraddr_id
and spraddr_mail_type = 'MA'

[〜#〜] vs [〜#〜]

select
    spriden_user_id as "ID",
    spriden_last_name as "last",
    spriden_first_name as "first",
    spriden_mi_name as "MI",
    spraddr_street_line1 as "Street",
    spraddr_street_line2 as "Street2",
    spraddr_city as "city",
    spraddr_stat_code as "State",
    spraddr_Zip as "Zip"
from spriden, spraddr
where spriden_user_id = spraddr_id
and spraddr_mail_type = 'MA'
group by "ID","last","first","MI","Street","Street2","city","State","Zip"     
16
Taku_

データベースはあなたが何を意味するかを認識するのに賢いです。どちらのクエリも同じように機能することを期待しています。あなたのクエリを維持している他の誰かがあなたが何を意味したかを知ることは重要です。本当に個別のレコードを取得する場合は、DISTINCTを使用してください。集計を行う場合は、GROUP BYを使用してください

この質問 を見てください。役立つかもしれないいくつかの素晴らしい答えがあります。

21
zedfoxus

@zedfoxusによって提供される回答は、コンテキストを理解するのに役立ちます。

ただし、データが正しく設計されている場合、クエリで個別のレコードが必要になるとは思いません。

テーブルspridenの主キーを選択しているように見えるので、そのすべてのデータshouldは一意です。また、spraddrテーブルに参加しています。そのテーブルには本当に有効な重複データが含まれていますか?それとも、それらの重複を除外するために必要な追加の参加基準がありますか?

これが、「distinct」の使用に神経質になる理由です。spraddrテーブルには、データを除外するために使用する必要のある追加の列が含まれている場合があり、「distinct」はそれを隠す。

また、パフォーマンスの問題を引き起こす可能性のある「distinct」句でフィルタリングする必要がある大規模な結果セットを生成している可能性があります。たとえば、spraddrの各行に対してspridenに100万行がある場合、「is_current」フラグを使用して2つまたは3つの「実際の」行を見つける必要があります。

最後に、「group by」がdistinctの代わりに使用されているのを見ると、「間違っている」という理由ではなく、スタイル的にはgroupbyを集計関数に使用する必要があると思います。それは個人的な好みです。

8
Neville Kuyt

あなたの例では、distinctgroup byは同じことをします。あなたの同僚は、クエリが最初に重複を返さないようにし、distinctまたはgroup by句なしでクエリを記述できるようにする必要があることを意味していると思います。 join条件を拡張することで、重複を減らすことができるかもしれません。

6
Alex

なぜそれが悪い習慣なのかを彼らに尋ねてください。多くの人が、本の最初のページやグーグル検索の最初の結果を読んで、ルールを作ったり、悪い習慣だと思うことを思いついたりします。それが仕事をし、問題を引き起こさないのであれば、代替案を見つけることによってより多くの仕事を生み出す理由はありません。あなたが投稿した2つのオプションから、私も別個のものを使用します。なぜなら、その短くて読みやすく、保守しやすいからです。

4
DonO

DISTINCTを使用していると言った人は、それ自体が悪い兆候です。実際には、それはすべて、最初にDISTINCTを使用して解決しようとしている問題によって異なります。

expectedであるテーブルにクエリを実行して、一部のフィールドまたはフィールドの組み合わせの値が繰り返され、値または値の組み合わせのリストをレポートしている場合(およびで集計を実行していない場合)それら)、そしてDISTINCTは使用するのに最も賢明なものです。誰かがDISTINCTを使用すべきではないと考えているという理由だけで、代わりにGROUP BYを使用することは私の頭の中ではあまり意味がありません。確かに、これはDISTINCTが設計されているようなものだと思います。

クエリに繰り返し値が返されることを意味するバグがあることがわかった場合は、このバグをキャンセルするためにDISTINCTまたはGROUP BYを使用しないでください。むしろ、バグの原因を突き止めて修正する必要があります。

セーフティネットとしてDISTINCTを使用することも、問題を隠す可能性があるため、不適切な方法です。さらに、計算コストが高くなる可能性があります(通常、O(nログn)またはO(n2))。このシナリオでは、代わりにGROUP BYを使用すると役立つとは思えません。

1
Stewart

はい、Distinctは、誰かの質問でそれに遭遇すると、頭の中で少し警告を発する傾向があります。もちろん必要な場合もありますが、ほとんどのデータモデルでは必要ありません。それを使用しなければならないための最後の手段、または異常値のケースになる傾向があります。また、データベースの上にある不良アプリケーションのシステムである可能性があり、重複するエントリを挿入または更新して重複させることができます(同様に、そのようなアクションを防ぐための対応するデータベースレベルの制約はありません)。したがって、最初に確認するのはデータです。これは、データモデルの設計が悪いことを示している可能性があります。ただし、重複する行が残っている選択では、クエリがその段階に到達しない可能性があります。

大規模なクエリを作成する場合、通常は一意のフィールドを指定するサブクエリのナゲットから開始します。その後のサブクエリは、内部結合または左結合する必要がありますが、ナゲットですでに定義されている行数を追加または削減することはできません。クエリ..そして左結合の可能なNULLを処理することを忘れないでください。

したがって、たとえば、ナゲットクエリは、パーティションを使用して適切な行を選択し、たとえば、結合されたテーブルの最新の行を選択したり、その段階で他のグループ化を行ったりすることができます。

あなたの例では、私は重複を期待していません。人が過去の住所を持つことができる場合は問題ありませんが、すべての住所を表示する必要がありますか、それとも最新の住所のみを表示する必要がありますか。同じ人の住所が重複している場合は、データが誤って重複していることを意味しますか、それとも人はそのアドレスを離れましたが、後で戻ってきました...この場合、パーティション選択は、個別よりもはるかに優れた制御でそれを修正します。特に、フィールドが後で他の誰かによってクエリに追加され、個別性を壊した場合。

これは、他のすべてのデータがサブクエリのこのナゲットからぶら下がっていることを意味します。他の可能なフィールドをコアのフィールドセットの右側に貼り付けます。

Distinctsが最後の手段である場合、それらは通常、データがそのフィールドのセットに対してそのテーブルに重複するエントリを持っていることがわかっている場合のために予約されており、それは完全に正常です。私の頭の中では、特にそれが返される大きな結果セットである場合、明確なものは計画の中で遅い、選択後のプロセスです。私はこれらの日のいずれかを確認する必要があります。

0
drew sutherland

クエリが正しければ、DISTINCTとGROUP BYは同じ結果セットを提供しますが、同僚はDISTINCTが問題を隠していると述べています。結合が欠落していてGROUPBYを使用している場合は、予想よりも多くの情報が返されます。結合が欠落していてDISTINCTを使用している場合、SQLエンジンは無制限(または部分的に制限された)結合を実行し、結果を絞り込んでから、期待される答えを考え出します。

必要以上のデータを生成することによる明らかなパフォーマンスの低下に加えて、tempdbがいっぱいになるリスクもあります(つまり、tempdbが存在するハードドライブのスペースが不足する)。

本番環境ではGROUPBYを使用してください。

0
Brad Allan