[英]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 行。
我很驚訝你自己沒有注意到這一點,因為你說你已經在使用查詢並且沒有發生聚合。 或者這就是您所說的“太多連接”?
不用交叉連接所有這些行,只需使用EXISTS
或IN
查找表。
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.