2013-04-15 3 views
1

시설, 직원, 완료 단위, 프로젝트 및 근무 교대를 저장하는 5 개의 테이블이 있습니다.복합 MYSQL 5 개 테이블 중에서 선택

시설에 프로젝트에 로그온 한 시간이있는 경우 각 시설에서 프로젝트의 생산성 (누적 완료 횟수 및 누적 시간)을 결정해야합니다. 기능은 직원 테이블에 저장됩니다. 여기

(이 질문에 대한 필요한 필드로 감소) 내 테이블 구조입니다 :

이 직원과 함께 저장됩니다
facilities 
+------------+ 
| id   | 
+------------+ 
| label  | 
+------------+ 

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

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

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

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

내가 시설에 대한 생산성을 선택하는 것입니다 문제로 실행하고,하지 교대 또는 # of 완료와 함께. 어쩌면 그게 디자인 결함일까요? 교대와 완료 테이블도 시설 칼럼을 가지고 있습니까? 직원이 이미 시설을 결정할 때 시설 열을 보유하는 것은 불필요한 것으로 보입니다.

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

이 내가 십자가가 가장 좋은 방법으로 가입 찾을 것이 드문 경우 중 하나입니다

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 

이 문제는 비교적 쉽게 경우 completes를 해결할 수 및 shifts이 저장되었습니다 같은 테이블. 그것은 당신의 필요에 따라 당신을 위해 작동하지 않을 수도 있지만 대체 스키마로 고려해야 할 것입니다.

관련 문제