2015-06-08 36 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