Работа с датами в MySQL. Общее количество реализованных различных проектов - PullRequest
4 голосов
/ 11 июля 2020

У меня есть таблица в старой версии MySQL 5.x, например:

+---------+------------+------------+
| Task_ID | Start_Date | End_Date   |
+---------+------------+------------+
|       1 | 2015-10-15 | 2015-10-16 |
|       2 | 2015-10-17 | 2015-10-18 |
|       3 | 2015-10-19 | 2015-10-20 |
|       4 | 2015-10-21 | 2015-10-22 |
|       5 | 2015-11-01 | 2015-11-02 |
|       6 | 2015-11-17 | 2015-11-18 |
|       7 | 2015-10-11 | 2015-10-12 |
|       8 | 2015-10-12 | 2015-10-13 |
|       9 | 2015-11-11 | 2015-11-12 |
|      10 | 2015-11-12 | 2015-11-13 |
|      11 | 2015-10-01 | 2015-10-02 |
|      12 | 2015-10-02 | 2015-10-03 |
|      13 | 2015-10-03 | 2015-10-04 |
|      14 | 2015-10-04 | 2015-10-05 |
|      15 | 2015-11-04 | 2015-11-05 |
|      16 | 2015-11-05 | 2015-11-06 |
|      17 | 2015-11-06 | 2015-11-07 |
|      18 | 2015-11-07 | 2015-11-08 |
|      19 | 2015-10-25 | 2015-10-26 |
|      20 | 2015-10-26 | 2015-10-27 |
|      21 | 2015-10-27 | 2015-10-28 |
|      22 | 2015-10-28 | 2015-10-29 |
|      23 | 2015-10-29 | 2015-10-30 |
|      24 | 2015-10-30 | 2015-10-31 |
+---------+------------+------------+

Если End_Date задач являются последовательными, то они являются частью одного проекта. Мне интересно узнать общее количество завершенных проектов.

Если существует несколько проектов с одинаковым количеством дней завершения, то заказывайте их по Start_Date проекту.

Для этих нескольких образцов записей ожидаемый результат будет:

2015-10-15 2015-10-16
2015-10-17 2015-10-18
2015-10-19 2015-10-20
2015-10-21 2015-10-22
2015-11-01 2015-11-02
2015-11-17 2015-11-18
2015-10-11 2015-10-13
2015-11-11 2015-11-13
2015-10-01 2015-10-05
2015-11-04 2015-11-08
2015-10-25 2015-10-31

Я немного сбит с толку. Буду очень признателен за любую помощь. Спасибо.

Ответы [ 3 ]

3 голосов
/ 15 июля 2020

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

Он создает две таблицы, одну с Start_Date, а другую с End_Date, что NOT IN End_Date и Start_Date соответственно из Projects table и запрашивать эти таблицы, выбирая Start_Date WHERE Start_Date < End_Date группировку по Start_Date, используя aggregate function MIN с End_Date, чтобы получить полный проект.

DATEDIFF(MIN(End_Date), Start_Date) для вычисления project_duration и возможность заказа project_duration .

SELECT Start_Date, MIN(End_Date) AS End_Date, DATEDIFF(MIN(End_Date), Start_Date) AS project_duration
FROM
    (SELECT Start_Date FROM Projects WHERE Start_Date NOT IN (SELECT End_Date FROM Projects)) a,
    (SELECT End_Date FROM Projects WHERE End_Date NOT IN (SELECT Start_Date FROM Projects)) b
WHERE Start_Date < End_Date
GROUP BY Start_Date
ORDER BY project_duration ASC, Start_Date ASC;

ожидаемый результат

+------------+------------+---------------+
| Start_Date | End_Date   | project_duration |
+------------+------------+---------------+
| 2015-10-15 | 2015-10-16 |             1 |
| 2015-10-17 | 2015-10-18 |             1 |
| 2015-10-19 | 2015-10-20 |             1 |
| 2015-10-21 | 2015-10-22 |             1 |
| 2015-11-01 | 2015-11-02 |             1 |
| 2015-11-17 | 2015-11-18 |             1 |
| 2015-10-11 | 2015-10-13 |             2 |
| 2015-11-11 | 2015-11-13 |             2 |
| 2015-10-01 | 2015-10-05 |             4 |
| 2015-11-04 | 2015-11-08 |             4 |
| 2015-10-25 | 2015-10-31 |             6 |
+------------+------------+---------------+
2 голосов
/ 11 июля 2020

Следующий запрос должен работать:

   select  tmp.projectid, date_sub(max(tmp.ed2), interval max(tmp.projectdays) day) start_date,
       max(tmp.ed2) end_date, 
      max(tmp.projectdays) No_Of_ProjectDays
from
(
select t1.task_id tid1, t1.start_date sd1, t1.end_date ed1,
       t2.task_id tid2, t2.start_date sd2, t2.end_date ed2,
     case when  datediff(t2.start_date, ifnull(t1.start_date,'1000-01-01')) != 1
          then  (@pid := @pid + 1)
          else  (@pid := @pid)
     end as ProjectId,
      case when  datediff(t2.start_date, ifnull(t1.start_date,'1000-01-01')) != 1
          then  (@pdays := 1) 
          else  (@pdays := @pdays + 1)
     end as ProjectDays
     from tasks t1 right join tasks t2
on t2.task_id = t1.task_id + 1
cross join (select @pid :=1, @pdays := 1) vars
) tmp
group by tmp.projectid
order by max(tmp.projectdays), start_date

Здесь вы найдете демонстрацию .

РЕДАКТИРОВАТЬ: Я внес изменения в запрос и ссылку по новому образцу данных. Пожалуйста, посмотрите.

2 голосов
/ 11 июля 2020

Это отвечает - и дает правильный ответ - на исходную версию этого вопроса.

Хмммм. . . Я думаю, вы можете использовать переменные. Самый простой способ - сгенерировать порядковый номер, а затем вычесть это значение, чтобы получить константу для соседних строк из даты:

select min(start_date), max(end_date)
from (select t.*, (@rn := @rn + 1) as rn
      from (select t.* from tasks t order by end_date) t cross join
           (select @rn := 0) params
     ) t
group by (end_date - interval rn day);

Здесь - скрипт db <>.

...