2015-06-08 33 views
3

我有三个表都与以下结构相关。关于分组/条款的MySQL多个条件

ModuleCategory表:

+------------------+----------------+------------+ 
| ModuleCategoryID | ModuleCategory | RequireAll | 
+------------------+----------------+------------+ 
|    90 | Cat A   | YES  | 
|    91 | Cat B   | NO   | 
+------------------+----------------+------------+ 

ModuleCategorySkill表:

+------------------+---------+ 
| ModuleCategoryID | SkillID | 
+------------------+---------+ 
|    90 | 1439 | 
|    90 | 3016 | 
|    91 | 1440 | 
|    91 | 3016 | 
+------------------+---------+ 

EmployeeSkill Table: 
+---------+---------+ 
| EmpName | SkillID | 
+---------+---------+ 
| Emp1 | 1439 | 
| Emp1 | 3016 | 
| Emp2 | 1440 | 
| Emp2 | 3016 | 
| Emp3 | 1439 | 
| Emp4 | 3016 | 
+---------+---------+ 

所需的输出:

+------------------+-------+ 
| ModuleCategory | Count | 
+------------------+-------+ 
|   Cat A |  1 | 
|   Cat B |  3 | 
+------------------+-------+ 

我想组由ModuleCategoryID的,并得到其拥有员工数技能被跟踪。

通常情况下,我可以做下面的查询获得的数字:

select mc.ModuleCategory, Count(*) as Count from ModuleCategory as mc 
join ModuleCategorySkill as mcs on mc.ModuleCategoryID = mcs.ModuleCategoryID join EmployeeSkill as es on es.SkillID= mcs.SkillID 
group by mc.ModuleCategoryID 

不过,我在这,如果它被设置为ModuleCategory表中的列RequireAll“YES”应该只算员工1只有当他们拥有该类别的所有技能时。如果它设置为NO,则它可以正常计数每行,并按其分组的行数增加计数。

我可以通过为每个modulecategoryID编写单独的查询并使用具有Count()> 1(它会找到任何具有ModuleCategoryID 90所有技能的人)来实现此目的。如果有3个技能,我将不得不将其更改为Having Count()> 2.如果没有任何人拥有指定的所有技能,则计数应该为0.

我需要一种动态方式能够做到这一点,因为有很多数据,并且为每个ModuleCategoryID写入一个查询不是正确的方法。

此外,我使用的PHP,所以我可以循环并创建一个SQL字符串,可以帮助我实现这一点。但是我知道我会碰到有大量技巧和modulecategoryID的大牌桌上的表现问题。

任何有关如何实现这一目标的指导都非常感谢。

回答

1

您可以通过加入总类数,然后使用条件聚集做到这一点:

select modulecategory, 
     count(case when requireall = 'yes' 
       then if(s = t, 1, null) 
       else s 
      end) 
from (    
select modulecategory,empname, requireall, count(*) s, min(q.total) t 
    from employeeskill e 
    inner join modulecategoryskill mcs 
     on e.skillid = mcs.skillid 
    inner join modulecategory mc 
     on mcs.modulecategoryid = mc.modulecategoryid 
    inner join (
     select modulecategoryid, count(*) total 
     from modulecategoryskill 
     group by modulecategoryid 
    ) q 
    on mc.modulecategoryid = q.modulecategoryid 
    group by modulecategory, empname 
) qq 
group by modulecategory; 

demo here

该雇员是不会被分配相同的假设下运行技能两次,如果这是可能发生的事情,这个查询是可以改变的,以支持它,但它似乎对我来说是一个破碎的场景。

我们这里有一个内部查询,用于整理我们需要的所有信息(类别名称,员工姓名,是否需要所有技能,每个员工组中有多少技能,以及组总计),外部查询使用条件计数来更改行的计算方式,具体取决于值requireall

+0

嗨pala_,感谢您的快速响应和解决方案!上面的查询绝对有效,但我想检查它是否是最有效的方式,因为当我单独运行查询并按照我的建议进行联合查询时,查询时间为0.811秒(我明白它不会如同动态),如果我按照你的方法,大约需要6秒。由于我只给出了最低限度的列和连接进行演示,因此我主要关注的是添加更多逻辑时,持续时间会增加。再次感谢您的解决方案!期待着您可能有的任何其他建议 – celik

+0

@celik如果上述情况特别缓慢,您的索引可能不适合我。你能为查询提供一个'explain'输出吗? –

+0

我玩过并重写了一些更有意义的连接。我能在0.171秒内获得相同的结果!谢谢你,你的逻辑绝对是正确的答案。 – celik