Вычислить даты и длительности в запросе MySQL - PullRequest
2 голосов
/ 19 декабря 2011

У меня есть пример таблицы (table_name: track_task), как показано ниже:

task_id     stage        log_date
----------------------------------------
   3          1      2011-06-01 08:36:21
   9          1      2011-06-03 12:35:47
   3          2      2011-06-05 14:25:42
  21          1      2011-06-11 13:03:34
   9          2      2011-06-11 15:25:57
   3          3      2011-06-12 10:16:09
  21          2      2011-06-15 15:30:29
   3          4      2011-06-22 15:34:33
  21          3      2011-06-23 12:53:49
   9          4      2011-06-25 16:25:08

Приведенные выше данные автоматически заполняются, когда на этапе задачи выполняется какое-либо действие в коде приложения. Этапы выполняются с 1 по 4. Однако из-за некоторой логики задача может пропустить этап 3. Но все задачи заканчиваются на этапе 4. Возможные пути выполнения задач выглядят следующим образом:

(1,2,3,4) / (1,2,4) - Completed tasks
(1,2,3) / (1,2)     - In progress tasks

Мне нужно запросить и получить отчет, который показывает, сколько времени (в днях) занимает задача на каждом этапе в данный момент времени. До сих пор я задавал следующий запрос:

SELECT z.task_id, a.log_date begin_date, d.log_date end_date, 
       DATEDIFF( b.log_date, a.log_date ) step1_days, 
       DATEDIFF( c.log_date, b.log_date ) step2_days, 
       DATEDIFF( d.log_date, c.log_date ) step3_days, 
       DATEDIFF( d.log_date, a.log_date ) cycle_days
FROM track_task z
LEFT JOIN track_task a ON ( z.task_id = a.task_id AND a.staging_id =1 )
LEFT JOIN track_task b ON ( z.task_id = b.task_id AND b.staging_id =2 )
LEFT JOIN track_task c ON ( z.task_id = c.task_id AND c.staging_id =3 )
LEFT JOIN track_task d ON ( z.task_id = d.task_id AND d.staging_id =4 )
GROUP BY z.oppty_id

для получения результирующего набора, как показано ниже:

task_id  begin_date   end_date   step1_days  step2_days  step3_days  cycle_days
-------------------------------------------------------------------------------
  3      2011-06-01  2011-06-22       4          7          10           21
  9      2011-06-03  2011-06-25       8         NULL       NULL          22
 21      2011-06-11     NULL          4          8         NULL         NULL

Это хороший способ сделать это или есть лучший способ? Как я могу получить значения NULL, сообщенные как ноль? Как я могу получить end_date для задачи, которая еще выполняется?

Ответы [ 3 ]

0 голосов
/ 19 декабря 2011

Нет предложений по улучшению общего подхода к проблеме.Тем не менее, вы можете сообщить NULL значения как 0 (или что-нибудь еще в этом отношении), используя функцию MySQL COALESCE http://dev.mysql.com/doc/refman/5.0/en/comparison-operators.html#function_coalesce.

Coalesce принимает список в качестве входных данных и возвращает первое ненулевое значение.

Например:

     SELECT z.task_id, a.log_date begin_date, d.log_date end_date, 
           COALESCE(DATEDIFF( b.log_date, a.log_date ),0) step1_days, 
           COALESCE(DATEDIFF( c.log_date, b.log_date ),0) step2_days,
...

Вернет 0, если step1_days или step2_days равно NULL.

0 голосов
/ 20 декабря 2011

О третьем вопросе, следующее редактирование запроса разрешает его.

SELECT z.task_id, a.log_date begin_date, e.log_date end_date, 
       COALESCE(DATEDIFF( b.log_date, a.log_date ),0) step1_days, 
       COALESCE(DATEDIFF( c.log_date, b.log_date ),0) step2_days, 
       COALESCE(DATEDIFF( d.log_date, c.log_date ),0) step3_days, 
       COALESCE(DATEDIFF( d.log_date, a.log_date ),0) cycle_days
FROM track_task z
LEFT JOIN track_task a ON ( z.task_id = a.task_id AND a.staging_id =1 )
LEFT JOIN track_task b ON ( z.task_id = b.task_id AND b.staging_id =2 )
LEFT JOIN track_task c ON ( z.task_id = c.task_id AND c.staging_id =3 )
LEFT JOIN track_task d ON ( z.task_id = d.task_id AND d.staging_id =4 )
LEFT JOIN track_task e ON ( z.task_id = e.task_id AND e.staging_id IN
    (
      SELECT max( staging_id )
      FROM z_table_trial
      GROUP BY oppty_id
    )
)
GROUP BY z.oppty_id
0 голосов
/ 19 декабря 2011

Это выглядит примерно так: как бы я сделал что-то подобное, предполагая, что когда-либо будет только один экземпляр stage, используемого на task (если нет, вам нужно больше работы, как для определения ваших требований, так и для написаниязапрос).

Чтобы null отображалось как 0, используйте функцию COALESCE():

SELECT z.task_id, COALESCE(DATEDIFF(b.log_date, a.log_date), 0) as step1_days
...