2014-02-06 6 views
0

мне нужно, чтобы получить минимальное и максимальное счет групповых идентификаторов, но только если они включены:Сложное мин/макс несколькими столами запросов

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  | 
-------------------- -------------------- -------------------- 

счеты находятся в отдельной таблице:

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 | 
---------------------------------- 

мне нужно, чтобы получить максимум и мин балл для каждого типа группы для только активных групп (для каждого типа):

--------------------------------------------- 
|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_groups со ссылкой на новую таблицу cdu_group_types и удалить столбец group_type от cdu_user_progress.

Если это установленный проект, в котором изменение структуры будет слишком разрушительным ... тогда один из других ответов, показывающих запрос, будет лучше/легче подходит.

В противном случае, вы могли бы упростить вещи с измененной структурой таблиц и в конечном итоге с запросом, как:

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. С помощью этой структуры вы можете добавлять новые типы групп по своему усмотрению (а также сокращать количество таблиц и объединений). Таблицы будут (упрощена в этом коде ниже, нет ФКС или что-нибудь):

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

Возможно, это самый быстрый способ выполнить этот запрос. Для оптимизации этого, вы должны иметь индекс group_id, enabled на каждом из трех «СЛ», «CC» и «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 
      ) 
    ) 

Как примечание, имеющее три таблицы с такой же структурой, как правило, признак плохой схемы базы данных. Эти три таблицы, вероятно, должны быть объединены в одну таблицу, что сделало бы этот запрос намного проще для записи.

Смежные вопросы