Я работаю над отчетами для нашего приложения для отслеживания времени.Каждый раз запись относится к проекту и услуге.Вот упрощенный запрос для группировки записей времени по проекту и услуге.
SELECT
projects.name as project_name,
services.name as service_name,
SUM(minutes) AS minutes
FROM `time_entries`
JOIN `projects` ON `projects`.id = `time_entries`.project_id
JOIN `services` ON `services`.id = `time_entries`.service_id
GROUP BY
time_entries.project_id,
time_entries.service_id
ORDER BY
max(minutes) DESC
Это приведет к такой таблице:
+---------------+--------------+---------+
| project_name | service_name | minutes |
+---------------+--------------+---------+
| Business Card | Consulting | 4800 |
| Microsite | Coding | 3200 |
| Microsite | Consulting | 2400 |
| Microsite | Design | 2400 |
| Business Card | Design | 800 |
+---------------+--------------+---------+
Что я пытаюсь достичь, хотя это возможность,сортировать по сумме проектных минут.Не проект «Визитная карточка» должен быть на вершине, а проект «Микросайт», потому что у него больше минут.
+---------------+--------------+-----------------+---------+
| project_name | service_name | project_minutes | minutes |
+---------------+--------------+-----------------+---------+
| Microsite | Coding | 8000 | 3200 |
| Microsite | Consulting | 8000 | 2400 |
| Microsite | Design | 8000 | 2400 |
| Business Card | Consulting | 5600 | 4800 |
| Business Card | Design | 5600 | 800 |
+---------------+--------------+-----------------+---------+
Единственный способ найти колонку »project_minutes« - этосначала создайте таблицу и соедините ее с собой.Запрос, который я предложил:
DROP TABLE IF EXISTS group2;
CREATE TABLE group2 SELECT
projects.id as project_id,
projects.name as project_name,
services.name as service_name,
SUM(minutes) AS minutes
FROM `time_entries`
JOIN `projects` ON `projects`.id = `time_entries`.project_id
JOIN `services` ON `services`.id = `time_entries`.service_id
GROUP BY
time_entries.project_id,
time_entries.service_id
ORDER BY
max(minutes) DESC
LIMIT 0, 30;
SELECT
project_name, service_name, project_minutes, minutes
FROM
group2
LEFT JOIN
(
SELECT project_id as project_id, sum(minutes) AS project_minutes
FROM group2
GROUP BY project_id
) as group1 on group1.project_id = group2.project_id
ORDER BY
project_minutes DESC,
minutes DESC;
Я даже не могу создать временную таблицу из-за ошибки MySQL (?): http://www.google.com/search?&q=site:bugs.mysql.com+reopen+temporary+table
Мои вопросы:
- Каков наилучший способ получить столбец наподобие »project_minutes«, который суммирует минуты групп и добавляет результат в виде дополнительного столбца?Есть ли хитрый SQL-трюк, о котором я не знаю?
- Если вы не нашли пути для моего первого вопроса, считаете ли вы целесообразным создание дополнительной таблицы для каждого запроса?Это быстрее, чем делать эту логику вручную после в коде?Мы используем Rails, в случае, если это что-то меняет.
Большое спасибо за вашу помощь!
ОБНОВЛЕНИЕ
Спасибо за ваши ответыдо сих пор.Я суммирую их, чтобы получить лучший обзор: http://gist.github.com/553560
Правильно ли я понимаю, что нет другого способа, кроме запроса таблицы time_entries один раз для каждой группы по выражению?Если да, вы видите проблемы с производительностью из-за следующих фактов:
- Таблица time_entries, безусловно, та, с наибольшим количеством строк (~ 4 миллиона)
- Пользователь может группироватьдо 6 столбцов.Посмотрите на этот скриншот: http://dl.dropbox.com/u/732913/time_entries_grouped_by_customer_project_service_user.png