簡體   English   中英

編寫包含太多聯接的查詢的最佳方法

[英]Best way to write a query with too many joins

我有一個數據庫表(我們稱之為project )和許多其他表,這些其他表中的大多數都有一個引用表project的外鍵( id_project )。

這個查詢的目標是返回項目現在處於哪個階段(一個項目一點一點地發展直到它結束)並且有超過20個項目可能經過的表,我對此的解決方案是使用太多加入並查看哪個表具有這樣的 null 個值

SELECT
    p.id_project
    CASE
        WHEN po.id IS NOT NULL THEN 'payment completed'
        WHEN b.id IS NOT NULL THEN 'bill received'
        WHEN e.id IS NOT NULL THEN 'project engaged'
        --(and still many other cases)
       ELSE 'start of the project'
    END AS progress
FROM 
    project p
LEFT JOIN
    decision d ON d.id_project = p.id_project
LEFT JOIN 
    engagement e ON e.id_project = p.id_project
LEFT JOIN 
    bill b ON b.id_project = p.id_project
LEFT JOIN 
    payment_order po ON po.id_project = p.id_project
LEFT JOIN  
    --..... (many other tables)

此查詢最多需要大約 9 秒來執行,並且使用得非常頻繁(作為從其他查詢調用的視圖)。

是否有可能有另一個更好的解決方案,或者是這種或另一種方法?

現在談談另一種方法? 一個項目目前只能處於一個階段; 正確的? 因此,您可以更改PROJECT表並添加一個新列 - PROJECT_PHASE - 其中將包含當前階段。 該專欄將在項目進入另一個階段后立即更新; 按照我的理解,它是在這 20 個表中的任何一個中創建新行的時候。

另一種選擇是創建一個新表project_phase ,其中將包含id_project和“id_phase”組合(以及時間戳等)。

任何方法都意味着您可以快速獲取當前項目階段,而無需外部連接 20 個(大?)表,這需要時間。

我們不知道您的數據,但您的數據庫設計顯示了所有表的 1:n 關系,即一個項目的多個決策、一個項目的多個參與、多個賬單等。現在讓我們假設有三個決策,三個參與到目前為止,一個項目有四張賬單。 您單獨加入項目 ID 上的所有行。 這稱為每個項目的笛卡爾積,創建所有組合(每一行與另一行)單獨為這個項目產生 3 x 3 x 4 = 36 行。

我很驚訝你自己沒有注意到這一點,因為你說你已經在使用查詢並且沒有發生聚合。 或者這就是您所說的“太多連接”?

不用交叉連接所有這些行,只需使用EXISTSIN查找表。

SELECT
  p.id_project,
  CASE
    WHEN p.id_project IN (SELECT po.id_project FROM payment_order po) THEN 'payment completed'
    WHEN p.id_project IN (SELECT b.id_project  FROM bill b)           THEN 'bill received'
    WHEN p.id_project IN (SELECT e.id_project  FROM engagement e)     THEN 'project engaged'
    -- (and still many other cases)
    ELSE 'start of the project'
  END AS progress
FROM project p;

一種更快的替代方法是按照 Littlefoot 的建議將狀態存儲在項目表中(理想情況下是狀態表),然后在所有更新該狀態的表上設置觸發器。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2025 STACKOOM.COM