группировать по годам по нескольким столбцам даты mysql - PullRequest
1 голос
/ 22 марта 2019

У меня есть следующая таблица:

hours  | ... | task_assigned  | task_deadline  | task_completion
----------------------------------------------------------------
123    | ... | 2019-08-01     | -              | -
234    | ... | -              | 2018-08-01     | 2019-08-01
145    | ... | 2017-08-01     | 2017-08-01     | 2018-01-01

Я хочу рассчитать общее количество часов для каждого года, то есть сгруппировать по годам.

В настоящее время я учитываю только task_completionfield.

Если в поле task_completion нет значения, запись не включается в вычисление SUM.

Более подробно, скажем, для year 2019, строка 1 и1 оба должны быть рассмотрены.Следовательно, общее количество часов должно составлять 123 + 234 = 357.

И для year 2018, строка 2 and 3.

Аналогично, для year 2017, строка 3.

SELECT YEAR(task_completion) as year, ROUND(SUM(total_hours), 2) as hours 
FROM task
GROUP BY year
HAVING year BETWEEN '$year_from' AND '$year_to'

Набор результатов:

year  |  hours
--------------------
2017  |  <somevalue>
2018  |  <somevalue>
2019  |  <somevalue>

Как я могу также включить два других поля даты?

Ответы [ 3 ]

2 голосов
/ 22 марта 2019

Вы хотите рассмотреть каждую строку один раз для каждого из ее лет. Используйте UNION, чтобы получить эти годы:

select year, round(sum(total_hours), 2) as hours
from
(
  select year(task_assigned) as year, total_hours from task
  union
  select year(task_deadline) as year, total_hours from task
  union
  select year(task_completion) as year, total_hours from task
) years_and_hours
group by year
having year between $year_from and $year_to
order by year;

Если вы хотите рассмотреть строку с одним годом в два раза или в три раза также как часто в сумме, то измените UNION на UNION ALL.

1 голос
/ 22 марта 2019

Как правило, вы хотите отключить данные. Я предполагаю, что - представляет значение NULL, а ваши даты являются реальными датами.

select year(dte) as year, sum(total_hours) as hours
from ((select task_assigned as dte, total_hours
       from task
      ) union all
      (select task_deadline, total_hours
       from task
      ) union all
      (select task_completion, total_hours
       from task
      )
     ) d
where dte is not null
group by year(dte)
order by year(dte);

Исходя из данных вашего примера, round() не требуется, поэтому я удалил его.

Если вы хотите фильтровать по определенным годам, фильтрация должна быть в предложении where - поэтому она фильтрует данные до агрегации.

Измените where на:

where year(dte) >= ? and year(dte) <= ?

или

where dte >= ? and dte <= ?

для передачи дат.

? для заполнителей параметров. Узнайте, как использовать параметры, а не манипулировать строками запроса.

0 голосов
/ 22 марта 2019

Этот ответ не является действительным с обновленным запросом.

Если я правильно понимаю, вы хотите использовать task_assigned, если task_completion по-прежнему нулевой. Для этого используйте COALEASCE.

SELECT
  YEAR(COALESCE(task_completion, task_assigned)) as year,
  ROUND(SUM(total_hours), 2) as hours
FROM task
GROUP BY year
HAVING year BETWEEN $year_from AND $year_to
ORDER BY year;

(Я не думаю, что вы на самом деле хотите использовать task_deadline также, для того, как задача может быть выполнена до того, как ее сначала назначат? Если это может произойти, включите ее в выражение COALESCE. Вероятно: COALESCE (task_completion, task_assigned, task_deadline) `затем.)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...