Mysql

使用 group by 過濾子查詢結果

  • June 15, 2017

我有一個有效的連接,但看起來很笨拙,因為它對子查詢進行排序並使用 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_sizeeffective-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      

我的問題:這種方法有問題嗎?有沒有更直接的方法來達到預期的結果?

您的查詢是非確定性的,因為它濫用GROUP BY.

它可能會在任何版本的 MySQL 中給出不正確/意外的結果,具體取決於執行計劃和可用索引。您可能沒有看到這樣的行為,因為它還沒有發生(您很幸運,或者表的索引和大小到目前為止已經導致了能夠給出正確結果的計劃)或者它發生了但您沒有註意到。

在某些版本(MariaDB 5.3+)中,類似的查詢——不確定這個但類似——幾乎總是會給出不正確的結果,因為一些優化會刪除ORDER BY子查詢中的冗餘。

如果您嘗試查詢,則在某些版本的 MySQL (5.7) 中會出現錯誤 - 正是因為它可能會給出不一致的結果。在該版本中,您必須更改預設設置(並獲得錯誤的非確定性行為),否則您必須重寫/更正查詢。

簡而言之,不要使用它。


我會這樣寫查詢。更簡單,確定性並且可能更有效,因為沒有GROUP BY並且不會pi兩次加入表:

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)將是進一步的幫助。

引用自:https://dba.stackexchange.com/questions/176383