2014-02-06 24 views
0

我需要的最小和組ID的最高分,但只有當它們被激活:複雜的最小/最大多表查詢

cdu_user_progress 
---------------------------------- 
|id |group_type |group_id |score | 
---------------------------------- 
|1 |sl   |1  |50 | 
|1 |cc   |1  |10 | 
|1 |ph   |1  |20 | 
|1 |sl   |2  |80 | 
|1 |sl   |3  |20 | 
|1 |cc   |3  |30 | 
|1 |sl   |1  |40 | 
|1 |ph   |1  |50 | 
|1 |cc   |1  |40 | 
|1 |ph   |2  |90 | 
---------------------------------- 

cdu_group_sl:   cdu_group_cc:   cdu_group_ph: 
-------------------- -------------------- -------------------- 
|id |name |enabled | |id |name |enabled | |id |name |enabled | 
-------------------- -------------------- -------------------- 
|1 |sl_1 |1  | |1 |cc_1 |1  | |1 |ph_1 |0  | 
|2 |sl_3 |1  | |2 |cc_2 |0  | |2 |ph_2 |1  | 
|3 |sl_4 |1  | |3 |cc_3 |1  | |3 |ph_3 |1  | 
-------------------- -------------------- -------------------- 

成績在一個單獨的表中找到

我需要爲才啓用組每種類型組的最大值和最小值的分數(每類):

--------------------------------------------- 
|group_type |group_id |min_score |max_score | 
--------------------------------------------- 
|sl   |1  |40  |50  | 
|sl   |2  |80  |80  | 
|sl   |3  |20  |20  | 
|cc   |1  |10  |40  | 
|cc   |3  |30  |30  | 
|ph   |1  |20  |50  | 
|ph   |2  |90  |90  | 
---------------------------------------------  

任何想法該查詢可能是?到目前爲止,我有:

SELECT * FROM cdu_user_progress 
JOIN cdu_group_sl ON (cdu_group_sl.id = cdu_user_progress.group_id AND cdu_user_progress.group_type = 'sl') 
JOIN cdu_group_cc ON (cdu_group_cc.id = cdu_user_progress.group_id AND cdu_user_progress.group_type = 'cc') 
JOIN cdu_group_ph ON (cdu_group_ph.id = cdu_user_progress.group_id AND cdu_user_progress.group_type = 'ph') 
WHERE cdu_user_progress.uid = $student->uid 
AND (cdu_user_progress.group_type = 'sl' AND cdu_group_sl.enabled = 1) 
AND (cdu_user_progress.group_type = 'cc' AND cdu_group_cc.enabled = 1) 
AND (cdu_user_progress.group_type = 'ph' AND cdu_group_ph.enabled = 1) 

可能完全錯誤的......

+0

你是什麼意思? – user3241112

回答

1

有關使用一個工會來接你感興趣的羣體是什麼 - 是這樣的:

select group_type, group_id min(score) min_score, max(score) max_score 
from (
    select id, 'sl' grp from cdu_group_sl where enabled = 1 
    union all 
    select id, 'cc' from cdu_group_cc where enabled = 1 
    union all 
    select id, 'ph' from cdu_group_ph where enabled = 1 
) grps join cdu_user_progress scr 
on grps.id = scr.group_id and grps.grp = scr.group_type 
group by scr.group_type, scr.group_id 
0

如果你只是啓動這個項目,我會建議改進你的數據結構。根據您所展示的內容,您只能參考表,並從cdu_user_progress中刪除group_type列,因此只能從cdu_groups表中受益。

如果這是一個已建立的項目,那麼在改變結構會造成太大的破壞性...那麼顯示查詢的其他答案之一將是更好/更容易的結果。

否則,你可以簡化事情重組表和落得像查詢:

SELECT group_type, 
    group_id, 
    MIN(score) as min_score, 
    MAX(score) as max_score 
FROM cdu_user_progress c 
INNER JOIN cdu_groups g 
    ON c.group_id=g.id 
INNER JOIN cdu_group_types t 
    ON g.group_type_id=t.id 
WHERE enabled=1 
GROUP BY group_type, group_id 

這顯示,與預期成果,在this SQLFiddle。有了這個結構,您可以隨意添加新的組類型(並減少表和聯接的數量)。表會(簡化下面這段代碼,沒有FKS或任何東西):

CREATE TABLE cdu_user_progress 
(id INT, group_id INT, score INT) 

CREATE TABLE cdu_group_types 
(id INT, group_type VARCHAR(3)) 

CREATE TABLE cdu_groups 
(id INT, group_type_id INT, name VARCHAR(10), enabled BIT NOT NULL DEFAULT 1) 

授予數據移動到一個新的結構可能是疼痛或不合理......但希望有把它做爲一個可能性或者只是咀嚼。

0

以下可能是執行此查詢的最快方法。爲了優化這個,你應該有這三個「SL」,「CC」對group_id, enabled的指標,「pH值」表格:

select cup.* 
from cdu_user_progress cup 
where (cup.group_type = 'sl' and 
     exists (select 1 
       from cdu_group_sl sl 
       where sl.id = cup.group_id and 
        sl.enabled = 1 
      ) 
    ) or 
     (cup.group_type = 'cc' and 
     exists (select 1 
       from cdu_group_cc cc 
       where cc.id = cup.group_id and 
        cc.enabled = 1 
      ) 
    ) or 
     (cup.group_type = 'ph' and 
     exists (select 1 
       from cdu_group_ph ph 
       where ph.id = cup.group_id and 
        ph.enabled = 1 
      ) 
    ) 

作爲一個說明,具有相同結構的三個表通常是一個糟糕的數據庫模式的跡象。這三個表格應該可以合併成一個表格,這將使得這個查詢更容易編寫。