2015-05-08 8 views
0

У меня есть одна таблица job_resultMySQL множественная группировка по одной таблице

CREATE TABLE job_result (
    node varchar(20) DEFAULT NULL, 
    jobId int(10) DEFAULT NULL, 
    subResult int(1) DEFAULT NULL 
) 

Таблица содержит множество узлов.

Каждый узел имеет много jobId.

У каждой работы есть много subResults (обычно менее 10).

Некоторые примеры данных, представленных

insert into job_result values ('A', 14, 0); 
insert into job_result values ('A', 15, 0); 
insert into job_result values ('A', 16, 1); 
insert into job_result values ('A', 17, 0); 
insert into job_result values ('A', 18, 1); 
insert into job_result values ('A', 19, 1); 
insert into job_result values ('A', 20, 0); 


insert into job_result values ('B', 1, 0); 
insert into job_result values ('B', 2, 0); 
insert into job_result values ('B', 3, 1); 
insert into job_result values ('B', 4, 1); 
insert into job_result values ('B', 5, 1); 
insert into job_result values ('B', 6, 1); 
insert into job_result values ('B', 7, 1); 


insert into job_result values ('C', 10, 0); 
insert into job_result values ('C', 11, 0); 
insert into job_result values ('C', 12, 0); 
insert into job_result values ('C', 13, 0); 
insert into job_result values ('C', 14, 0); 
insert into job_result values ('C', 15, 0); 
insert into job_result values ('C', 16, 0); 

Я хочу, чтобы запрос, чтобы дать мне «проверку здоровья» на каждом узле, чтобы увидеть, если узел был X последовательно неудачные работы. Неудачное задание - это jobId, у которого есть хотя бы один ненулевой результат.

SELECT node, jobId, SUM(subResult) res 
FROM job_result WHERE node = 'A' 
GROUP BY jobId 
ORDER BY jobId desc 
LIMIT 5 

Это дает мне результат последней 5 работы на узле А, где 0 указывает на хорошую работу.

+------+---------+------+ 
| node | jobId | res | 
+------+---------+------+ 
| A | 20 | 0 | 
| A | 19 | 1 | 
| A | 18 | 1 | 
| A | 17 | 0 | 
| A | 16 | 1 | 

Тогда мне нужно суммировать и сгруппировать результаты в одной строке на узле, и я получил это далеко:

SELECT node, SUM(I.res) res 
FROM 
(SELECT node, sum(subResult) res 
FROM job_result WHERE node = 'A' 
GROUP BY jobId 
ORDER BY jobId desc 
LIMIT 5) I 

+------+------+ 
| node | res | 
+------+------+ 
| A | 3 | 

Мой вопрос: Как я могу расширить этот запрос, чтобы вернуть одну строку для каждого узла ? Я пробовал несколько дней с коррелированными подзапросами и объединениями, но я всегда терпит неудачу из-за внутреннего выбора, который не может видеть, какой узел выбрать. И когда это будет на месте, я буду работать над изменением LIMIT 5 на динамическое значение.

Желаемый результат был бы как

+------+------+ 
| node | res | 
+------+------+ 
| A | 3 | 
| B | 0 | 
| C | 1 | 
| E | 0 | 

Одна строка для каждого узла, с правой колонке с указанием числа не удается

Пожалуйста, посоветуйте!

+4

Почему бы не обеспечить надлежащие DDL и желаемый результат? (Я не понимаю, почему люди этого не делают.) – Strawberry

+0

Хорошая точка, добавление таблицы добавлено и желаемые результаты визуализируются –

ответ

1

В MySQL на большой таблице наилучшим подходом к получению последних 5 является использование переменных для перечисления результатов. Остальное представляет собой просто агрегацию:

SELECT node, SUM(subr > 0) as numfails 
FROM (SELECT node, jobid, subr, 
      (@rn := if(@n = node, @rn + 1, 
         if(@n := node, 1, 1) 
         ) 
      ) as rn 
     FROM (SELECT node, jobid, 
        SUM(subresult) as subr 
      FROM job_result jr 
      GROUP BY node, jobid 
      ) jr CROSS JOIN 
      (SELECT @n := '', @rn := 0) init 
     ORDER BY node, jobid desc 
    ) nr 
WHERE rn <= 5 
GROUP BY node; 
+0

Это работает, спасибо! На моей реальной базе данных с 3 миллионами строк требуется 42 секунды, что немного выше ... План выполнения «недоступен для оператора» ... –

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