2013-04-15 72 views
1

我有五個表格存儲設施,員工,完成的單位,項目和班次。複雜的MYSQL從5個表中選擇

我需要確定每個設施的項目的生產力(完成累計數和累積小時數),如果該設施有登錄項目的小時數。該設施存儲在員工表中。

這裏是我的表結構,(減少到必要的字段爲這個問題):

facilities 
+------------+ 
| id   | 
+------------+ 
| label  | 
+------------+ 

employees 
+------------+ 
| id   | 
+------------+ 
| facility | 
+------------+ 

completes 
+------------+ 
| id   | 
+------------+ 
| project | 
+------------+ 
| completes | 
+------------+ 
| employee | 
+------------+ 

projects 
+------------+ 
| id   | 
+------------+ 
| title  | 
+------------+ 

shifts 
+------------+ 
| id   | 
+------------+ 
| project | 
+------------+ 
| length  | 
+------------+ 
| employee | 
+------------+ 

當我遇到麻煩的是選擇生產的工廠,當存儲與員工,不與轉變或#完成。也許這是一個設計缺陷?班次和完成表是否也有設施專欄?當員工已經確定設施時,擁有設施欄似乎是多餘的。

SELECT p.title, SUM(c.completes), SUM(s.length) 
FROM projects as p 
LEFT JOIN completes as c ON c.project = p.id 
LEFT JOIN shifts as s ON s.project = p.id 
GROUP BY p.id, shifts.employee.facility; 

GROUP BY聲明當然是無效的。但它表明了我想要完成的事情。我還想在聲明中選擇設施標籤。我如何解決這個問題?

在此先感謝您提供的任何見解!

回答

1

這是罕見的情況之一,我會找到一個CROSS JOIN是最好的辦法:

SELECT p.title, f.label, SUM(c.completes), SUM(s.length) 
FROM facilities as f   
CROSS JOIN projects as p 
JOIN employees as e ON f.id = e.facility 
LEFT JOIN completes as c ON c.employee = e.id AND c.project = p.id 
LEFT JOIN shifts as s ON s.employee = e.id AND s.project = p.id 
WHERE c.id IS NOT NULL OR s.id IS NOT NULL 
GROUP BY p.id, p.title, f.id, f.label 

這本身不是一個不好的設計,但它確實讓人很難,你可以」在這裏使用典型的親子關係,因爲completesshifts表中實際上有2位父母。

另一種方法是使用沒有LEFT JOIN的UNION。這可能會返回一個更快的結果,這取決於行的數量目前在facilitiesprojects表:

SELECT p.title, 
     f.label, 
     SUM(CASE aggregated.type WHEN 'completes' THEN units ELSE 0 END), 
     SUM(CASE aggregated.type WHEN 'shifts' THEN units ELSE 0 END) 
FROM (
    SELECT 'completes' as type, project, employee, completes as units 
    FROM completes 
    UNION 
    SELECT 'shifts', project, employee, length 
    FROM shifts) aggregated 
JOIN projects as p ON aggregated.project = p.id 
JOIN employees as e ON aggregated.employee = e.id 
JOIN facilities as f ON e.facility = f.id 
GROUP BY p.id, p.title, f.id, f.label 

你可以從這個查詢看到,這個問題可以很解決很容易,如果completesshifts分別存放在同一張桌子。根據您的需求,這可能不適合您,但可能需要考慮將其作爲替代方案。