简体   繁体   English

从5个表格中选择复杂的MYSQL

[英]Complex MYSQL select from 5 tables

I have five tables storing facilities, employees, completed units, projects, and shifts. 我有五个表,分别存储设施,员工,已完成的单位,项目和班次。

I need to determine the productivity (cumulative # of completes and cumulative hours) of a project at each facility, if the facility has hours logged on the project. 如果工厂在项目上记录了小时数,则我需要确定每个设施上项目的生产率(完成数量和累积小时数)。 The facility is stored in the employee table. 该设施存储在员工表中。

Here is my table structure, (reduced to necessary fields for this question ): 这是我的表结构,(简化为该问题的必要字段):

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

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

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

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

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

Where I am running into trouble is selecting the productivity for a facility, when it is stored with the employee, not with the shift or the # of completes. 我遇到麻烦的地方是,选择设施的生产力时,是将其存储在员工手中,而不是班次或完成数量。 Maybe that is a design flaw? 也许这是设计缺陷? Should the shift and completes table also have a facility column? 班次和完成表还应该有一个设施栏吗? It seems redundant to have a facility column, when the employee already determines the facility. 当员工已经确定设施时,拥有设施列似乎是多余的。

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;

That GROUP BY statement of course is not valid. 该GROUP BY语句当然是无效的。 But it demonstrates what I want to accomplish. 但这说明了我想要完成的事情。 I would also like to select the facility label in the statement. 我还想在语句中选择设施标签。 How do I approach this? 我该如何处理?

Thanks in advance for any insight you can provide! 预先感谢您提供的任何见解!

This is one of the rare instances that I would find a CROSS JOIN to be the best approach: 这是我发现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

This isn't inherently a bad design, but it does make it difficult that you can't use the typical parent-child relationships here since there are actually 2 parents on your completes and shifts tables. 这从本质上来说并不是一个糟糕的设计,但是由于您的completes表和shifts表上实际上有2个父级,因此您很难使用典型的父子关系。

An alternative approach would to use a UNION without the LEFT JOINs. 另一种方法是使用不带LEFT JOIN的UNION。 This may return a faster result, depending on the amount of rows currently in your facilities and projects tables: 根据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

As you can see from this query, the problem could be solved fairly easily if completes and shifts were stored in the same table. 从该查询可以看到,如果将completesshifts存储在同一张表中,则可以很容易地解决问题。 That might not work for you depending on your needs, but it may be something to consider as an alternative schema. 根据您的需求,这可能对您不起作用,但是可能需要考虑将其作为替代方案。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM