2013-08-08 3 views
0

У меня есть две таблицы, image и gradeReason. Каждому изображению присуждается оценка за его качество, и пользователь может выбрать 4 различных причины (reasonID_1, reasonID_2, reasonID_3, reasonID_4), используя выбор reasonID. Разбивка причины хранится в таблице gradeReason.Борьба с подзапросом MySQL

image 

imageID auditID reasonID_1 reasonID_2 reasonID_3 reasonID_4 
------- ------- ---------- ---------- ---------- ---------- 
1   123  1   13   7   3 
2   124  8   13   8   6 
4   125  3   2   5   6 
5   125  7   4   2   3 

gradeReason 

reasonID category name 
-------- -------- ---- 
1   exposure overexposed 
2   exposure underexposed 
3   patient patient moved 
4   equipment sensor too big 
5   equipment sensor too small 

То, что я хотел бы запрос, который возвращает количество раз каждый reasonID использовался при проведении аудита и что имя gradeReason было

например

аудит 125 -

reasonID 3 был использован дважды - имя 'пациент переехал',

reasonID 2 используется дважды - имя 'недодержано'.

Буду честным и говорю, что я боролся с этим в течение многих дней, и я даже не могу думать, с чего начать.

+0

я строчил на клочки псевдокоде, пытаясь разбить его, потому что я предполагаю, что она нуждается в подзапрос, но именно там я застрял, так фактический код sql, ничего – tatty27

ответ

5

Это сложнее, потому что ваши данные неправильно нормализованы. Следующий подход первым нормализует данные, а затем делает соединение и агрегация:

select ir.auditId, gr.ReasonId, gr.category, gr.name, count(*) as cnt 
from (select i.imageID, i.auditID, 
      (case when n.n = 1 then ReasonID_1 
        when n.n = 2 then ReasonID_2 
        when n.n = 3 then ReasonID_3 
        when n.n = 4 then ReasonID_4 
       end) as ReasonId 
     from image i cross join 
      (select 1 as n union all select 2 union all select 3 union all select 4 
      ) n 
    ) ir join 
     gradeReason gr 
     on ir.ReasonId = gr.ReasonId 
group by ir.auditId, gr.ReasonId, gr.category, gr.name 
order by cnt desc; 
+0

Спасибо за это, но я не понимаю, как я получаю информацию из этого, мне нужно. Я попытался добавить WHERE ir.auditId = 13751316481858293091 после групповой строки, но я получаю синтаксическую ошибку sql – tatty27

+0

@ tatty27 'WHERE' предложение должно быть перед предложением GROUP BY' ... вот почему вы получили ошибку – Stephan

0

Для вашего выбора, вы должны присоединиться gradeReason один раз для каждого внешнего ключа gradeReason:

SELECT imageID 
     , auditID 
     , r1.name 
     , r2.name 
     , r3.name 
     , r4.name 
    FROM image i 
LEFT JOIN gradeReason r1 on i.reasonID_1 = r1.reasonID 
LEFT JOIN gradeReason r2 on i.reasonID_2 = r2.reasonID 
LEFT JOIN gradeReason r3 on i.reasonID_3 = r3.reasonID 
LEFT JOIN gradeReason r4 on i.reasonID_4 = r4.reasonID 

Вашего пример данными являются неразумно, так как внешние ключи к gradeReason в вашем изображении стола не находятся в классеReason, но, я думаю, у вас больше очков рейтинга в вашем рукаве.

Кроме того, ваша структура не нормируется: gradeReason имеет повторяющиеся записи в строках для категории. Это не так уж плохо, но было бы неплохо иметь отдельную таблицу gradeReasonCategories.

+0

Цель страницы, так что пользователи могут добавлять свои собственные причины, в том числе свои собственные категории и т. д. Идея заключается в том, что пользователь создает свою собственную причину, она добавляется в таблицу gradeReason, а идентификатор причины сохраняется в таблице изображений, когда они выбирают эту причину , Вы правы, когда говорите, что есть больше причин, я просто положил достаточно, чтобы вы видели, как выглядит таблица. Каждое из значений reasonID в таблице изображений либо имеет соответствующие значения в таблице изображений, либо причина еще не была использована пользователем – tatty27

0

Другой вариант использования СОЮЗЫ: -

SELECT auditId, ReasonId, category, name, SUM(cnt) 
FROM 
(
    SELECT ir.auditId, gr.ReasonId, gr.category, gr.name, count(*) as cnt 
    FROM image ir 
    INNER JOIN gradeReason gr 
    ON ir.reasonID_1 = gr.ReasonId 
    WHERE ir.auditId = 123 
    GROUP BY ir.auditId, gr.ReasonId, gr.category, gr.name 
    UNION ALL 
    SELECT ir.auditId, gr.ReasonId, gr.category, gr.name, count(*) as cnt 
    FROM image ir 
    INNER JOIN gradeReason gr 
    ON ir.reasonID_2 = gr.ReasonId 
    WHERE ir.auditId = 123 
    GROUP BY ir.auditId, gr.ReasonId, gr.category, gr.name 
    UNION ALL 
    SELECT ir.auditId, gr.ReasonId, gr.category, gr.name, count(*) as cnt 
    FROM image ir 
    INNER JOIN gradeReason gr 
    ON ir.reasonID_3 = gr.ReasonId 
    WHERE ir.auditId = 123 
    GROUP BY ir.auditId, gr.ReasonId, gr.category, gr.name 
    UNION ALL 
    SELECT ir.auditId, gr.ReasonId, gr.category, gr.name, count(*) as cnt 
    FROM image ir 
    INNER JOIN gradeReason gr 
    ON ir.reasonID_4 = gr.ReasonId 
    WHERE ir.auditId = 123 
    GROUP BY ir.auditId, gr.ReasonId, gr.category, gr.name 
) Sub1 
GROUP BY auditId, ReasonId, category, name 
Смежные вопросы