sql >> データベース >  >> RDS >> Mysql

JOIN内でDISTINCTを使用すると、問題が発生します

    1つのアプローチは、すでに持っているクエリのように、インラインビューを使用することです。ただし、DISTINCTを使用する代わりに、GROUPBYを使用して重複を排除します。要件を満たすための最も単純なインラインビューは次のとおりです。

    ( SELECT n.item_number, n.name, n.type_code
        FROM itpitnam n
       GROUP BY n.item_number
    ) itpitnam
    

    itpitnamのどの行から取得されるかについては決定論的ではありませんが、nameとtype_codeの値はそこから取得されます。より精巧なインラインビューにより、これをより具体的にすることができます。

    このタイプの問題に対する別の一般的なアプローチは、SELECTリストで相関サブクエリを使用することです。小さな行のセットを返す場合、これはかなりうまく機能します。ただし、大きなセットを返す場合は、より効率的なアプローチがあります。

    SELECT i.identifier
         , i.name
         , i.subtitle
         , i.description
         , i.itemimg 
         , i.mainprice
         , i.upc
         , i.isbn
         , i.weight
         , i.pages
         , i.publisher
         , i.medium_abbr
         , i.medium_desc
         , i.series_abbr
         , i.series_desc
         , i.voicing_desc
         , i.pianolevel_desc
         , i.bandgrade_desc
         , i.category_code
         , r.overall_ranking
         , ( SELECT n1.name
               FROM itpitnam n1
              WHERE n1.item_number = r.item_number
              ORDER BY n1.type_code, n1.name
              LIMIT 1
           ) AS artist
         , ( SELECT n2.type_code
               FROM itpitnam n2
              WHERE n2.item_number = r.item_number
              ORDER BY n2.type_code, n2.name
              LIMIT 1
           ) AS type_code
      FROM itpitems i
      JOIN itprank r
        ON r.item_number = i.identifier
     WHERE mainprice > 1
     LIMIT 3
    

    そのクエリは、1つの重要な違いを除いて、指定された結果セットを返します。元のクエリは、itpitnamへの内部結合を示しています テーブル。つまり、itpitnamに一致する行がある場合にのみ行が返されます。 テーブル。ただし、上記のクエリはOUTER JOINをエミュレートし、itpitnamに一致する行が見つからない場合、クエリは行を返します。 。

    更新

    これらの相関サブクエリのパフォーマンスを最高にするには、適切なインデックスを利用できるようにする必要があります。

    ... ON itpitnam (item_number, type_code, name)
    

    このインデックスは「カバーインデックス」であり、基になるテーブルのデータページを参照せずにインデックスからクエリを完全に満たすことができ、先頭の列に等式述語があり、次の2つの列にORDER BYがあるため、このインデックスが最も適切です。これにより、「ソート」操作が回避されます。

    -

    type_codeのいずれかが保証されている場合 またはname itpitnamテーブルの列がNULLでない場合、述語を追加して、一致する行が「欠落している」行を削除できます。例:

    HAVING artist IS NOT NULL
    

    (これを追加すると、パフォーマンスに影響を与える可能性があります。)この種の保証がない場合、INNER JOINの動作を取得するには、INNERJOINまたは一致する行の存在をテストする述語を追加する必要があります。

    >

    1. Flaskを使用した分離レベル-SQLAlchemy

    2. Oracleで休止状態:StringプロパティをCLOB列にマッピング

    3. SQLでカウント順に並べ替える方法は?

    4. SQLの使用方法-INSERT...ON DUPLICATE KEY UPDATE?