web-dev-qa-db-ja.com

グループ化によるサブクエリ結果のフィルタリング

私は動作する結合を持っていますが、サブクエリを順序付けし、最上位のサブクエリの結果以外のすべてをフィルタリングするためにgroup byを使用しているため、ハッキリしているようです。そうしないと、sとprint_issues.pub_dateのデカルト積が返されます。

SELECT 
    print_issues.pub_date, 
    print_issues.x,
    s.page_size 
FROM print_issues, 
  ( select pub_date, page_size 
    from print_page_size, 
          print_issues 
    where effective_date < print_issues.pub_date 
    order by effective_date desc
  ) as s 
WHERE s.pub_date = print_issues.pub_date 
group by print_issues.pub_date 
order by print_issues.pub_date desc

クエリは、print_page_sizeのスキーマのアーティファクトです。そのテーブルには、列page_sizeおよびeffective-dateがあります。 effective_dateが大きい新しいエントリは古いエントリに優先します。クエリの目的は、各号が発行されたときに有効なprint_issueテーブルをpage_sizeと統合することです。

Sample Data:

TABLE: print_page_size
======================
effective_date      page_size
2014-01-01          100
2017-05-01          105

TABLE: print_issues
===================
pub_date      x
2017-04-26    "Random"
2017-05-02    "Data"

OUTPUT
======
print_issues.pub_date          print_issues.x    s.page_size
2017-04-26                     "Random"          100
2017-05-02                     "Data"            105      

私の質問:このアプローチに問題はありますか?望ましい結果を達成するためのより直接的な方法はありますか?

1
AndrewE

_GROUP BY_を悪用するため、クエリは非決定的です。

実行プランと使用可能なインデックスによっては、MySQLのどのバージョンでも正しくない/予期しない結果になる可能性があります。このような動作はまだ発生していないために発生しなかった可能性があります(運が良かったか、テーブルのインデックスとサイズによって現在まで正しい結果が得られるプランにつながっていた)、または発生したが気付かなかった。

サブクエリ内の冗長な_ORDER BY_を削除するいくつかの最適化により、同様のクエリ(これについては不明ですが同様)がほとんど常に正しくない結果をもたらすバージョン(MariaDB 5.3+)があります。

MySQL(5.7)のバージョンには、クエリを実行するとエラーが発生するものがあります。これは、一貫性のない結果をもたらす可能性があるためです。そのバージョンでは、デフォルトの設定を変更する(そして、非決定的な動作を誤る)か、クエリを書き直すか修正する必要があります。

つまり、使用しないでください。


このようなクエリを作成します。 _GROUP BY_がなく、piテーブルを2回結合しないので、はるかに単純で、決定論的で、おそらくより効率的です。

_SELECT 
         pi.pub_date, 
         pi.x,
         ( SELECT   pps.page_size
           FROM     print_page_size AS pps
           WHERE    pps.effective_date < pi.pub_date
           ORDER BY pps.effective_date DESC
           LIMIT    1
         ) AS page_size
FROM  
         print_issues AS pi
ORDER BY 
         pub_date ;              -- or whatever
_

print_page_size (effective_date, pagesize)のインデックスはさらに役立ちます。

2
ypercubeᵀᴹ