Рассчитать количество открытых дел за день - PullRequest
1 голос
/ 01 мая 2020

Я работаю над запросами, основанными на времени, и я хотел бы получить оптимальный способ подсчета открытых дел в течение дня. У меня есть таблица task_interval, которая имеет 2 столбца start и end.

JSON пример:

[
    {
        "start" : "2019-10-15 20:41:38",
        "end" : "2019-10-16 01:44:03"
    },
    {
        "start" : "2019-10-15 20:43:52",
        "end" : "2019-10-15 22:18:54"
    },
    {
        "start" : "2019-10-16 20:21:38",
        "end" : null,
    },
    {
        "start" : "2019-10-17 01:42:35",
        "end" : null
    },
    {
        "create_time" : "2019-10-17 03:15:57",
        "end_time" : "2019-10-17 04:14:17"
    },
    {
        "start" : "2019-10-17 03:16:44",
        "end" : "2019-10-17 04:14:31"
    },
    {
        "start" : "2019-10-17 04:15:23",
        "end" : "2019-10-17 04:53:28"
    },
    {
        "start" : "2019-10-17 04:15:23",
        "end" : null,
    },
]

Результат запроса должен возвращать:

[
    { time: '2019-10-15', value: 1 },
    { time: '2019-10-16', value: 1 }, // Not 2! One task from 15th has ended
    { time: '2019-10-17', value: 3 }, // We take 1 continues task from 16th and add 2 from 17th which has no end in same day
]

Я написал запрос, который будет возвращать совокупную сумму запущенных задач, дата окончания которых не совпадает с датой начала:

SELECT 
    time,
    @running_total:=@running_total + tickets_number AS cumulative_sum
FROM
    (SELECT 
        CAST(ti.start AS DATE) start,
            COUNT(*) AS tickets_number
    FROM
        ticket_interval ti
    WHERE
        DATEDIFF(ti.start, ti.end) != 0
            OR ti.end IS NULL
    GROUP BY CAST(ti.start AS DATE)) X
        JOIN
    (SELECT @running_total:=0) total;    

1 Ответ

1 голос
/ 01 мая 2020

Если вы работаете с MySQL 8.0, один из вариантов - это отключить, затем агрегировать и выполнить сумму окна, чтобы вычислить счетчик бегов:

select 
    date(dt) dt_day, 
    sum(sum(no_tasks)) over(order by date(dt)) no_tasks 
from (
    select start_dt dt, 1 no_tasks from mytable
    union all select end_dt, -1 from mytable where end_dt is not null
) t
group by date(dt)
order by dt_day

Примечание: start и end зарезервированные слова, следовательно, не очень хороший выбор для имен столбцов. Я переименовал их в start_dt и end_dt.


. В более ранних версиях мы могли эмулировать сумму окна с помощью пользовательской переменной, например:

select 
    dt_day, 
    @no_tasks := @no_tasks + no_tasks no_tasks 
from (
    select date(dt) dt_day, sum(no_tasks) no_tasks
    from (
        select start_dt dt, 1 no_tasks from mytable
        union all select end_dt, -1 from mytable where end_dt is not null
    ) t
    group by dt_day
    order by dt_day
) t
cross join (select @no_tasks := 0) x
order by dt_day

Демонстрация на БД Fiddle - оба запроса дают:

dt_day     | no_tasks
:--------- | -------:
2019-10-15 |        1
2019-10-16 |        1
2019-10-17 |        3
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...