SQL-запрос для преобразования журнала изменений в интервалы

57
4

Итак, позвольте мне описать проблему:
У -I есть таблица задач со столбцом уполномоченного, созданным столбцом и разрешенным столбцом (и созданные, и разрешенные являются временными метками)

+---------+----------+------------+------------+  
| task_id | assignee | created | resolved |
+---------+----------+------------+------------+
| tsk1 | him | 2000-01-01 | 2018-01-03 |
+---------+----------+------------+------------+

У -I есть таблица журнала изменений с идентификатором task_id, столбцом from, столбцом a to и столбцом даты, который записывает каждый раз при изменении правопреемника

+---------+----------+------------+------------+  
| task_id | from | to | date |
+---------+----------+------------+------------+
| tsk1 | me | you | 2017-04-06 |
+---------+----------+------------+------------+
| tsk1 | you | him | 2017-04-08 |
+---------+----------+------------+------------+

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

+---------+----------+------------+------------+  
| task_id | assignee | from | to |
+---------+----------+------------+------------+
| tsk1 | me | 2000-01-01 | 2017-04-06 |
+---------+----------+------------+------------+
| tsk1 | you | 2017-04-06 | 2017-04-08 |
+---------+----------+------------+------------+
| tsk1 | him | 2017-04-08 | 2018-01-03 |
+---------+----------+------------+------------+

У меня проблемы с первой (/последней) строкой, где значение from (/to) должно быть установлено как созданное (/resolved), я не знаю, как сделать столбец с данными из двух разных таблиц...
Я пытался сделать их по своему выбору, а затем объединить все строки с объединением, но я не думаю, что это очень хорошее решение...

спросил(а) 2018-12-11T17:43:00+03:00 1 год, 10 месяцев назад
1
Решение
58

Ммм , , Это хитрее, чем кажется. Идея состоит в том, чтобы использовать lead() для получения следующей даты, но вам нужно "дополнить" данные информацией из таблицы tasks:

select task_id, to, date as fromdate,
coalesce(lead(date) over (partition by task_id order by date),
max(resolved) over (partition by task_id)
) as todate
from ((select task_id, to, date, null::timestamp
from log l
) union all
(select distint on (t.task_id) t.task_id, l.from, t.created, t.resolved
from task t join
log l
on t.task_id = l.task_id
order by t.task_id, l.date
)
) t;

ответил(а) 2018-12-11T17:55:00+03:00 1 год, 10 месяцев назад
41

Благодаря ответу S-Man и Гордона Линоффа я смог придумать это решение:

SELECT t.task_id,
t.item_from AS assignee,
COALESCE(lag(t.changelog_created) OVER (
PARTITION BY t.task_id ORDER BY t.changelog_created),
max(t.creationdate) OVER (PARTITION BY t.task_id)) AS fromdate,
t.changelog_created as todate
FROM ( SELECT ch.task_id,
ch.item_from,
ch.changelog_created,
NULL::timestamp without time zone AS creationdate
FROM changelog_generic_expanded_view ch
WHERE ch.field::text = 'assignee'::text
UNION ALL
( SELECT DISTINCT ON (t_1.id_task) t_1.id_task,
t_1.assigneekey,
t_1.resolutiondate,
t_1.creationdate
FROM task_jira t_1
ORDER BY t_1.id_task)) t;

Примечание: это окончательная версия, поэтому имена немного отличаются, но идея остается прежней.

Это в основном тот же код, что и у Гордона Линоффа, но я делаю журнал изменений в обратном направлении.
Я использую 2-ю часть UNION ALL, чтобы сгенерировать последнего правопреемника вместо первого (это для обработки случая, когда вообще нет журнала изменений, последний правопреемник генерируется без привлечения изменений)

ответил(а) 2018-12-12T17:50:00+03:00 1 год, 10 месяцев назад
41

демо: дб <> скрипка

SELECT 
l.task_id,
assignee_from as assignee,
COALESCE(
lag(assign_date) OVER (ORDER BY assign_date),
created
) as date_from,
assign_date as date_to
FROM
log l
JOIN
task t
ON l.task_id = t.task_id

UNION ALL

SELECT * FROM (
SELECT DISTINCT ON (l.task_id)
l.task_id, assignee_to, assign_date, resolved
FROM
log l
JOIN
task t
ON l.task_id = t.task_id
ORDER BY l.task_id, assign_date DESC
) s

ORDER BY task_id, date_from

UNION состоит из двух частей: часть из журнала и, наконец, последняя строка из таблицы задач.

Первая часть использует оконную функцию LAG() для получения предыдущей даты в текущей строке. Поскольку у "me" нет предыдущей строки, это приведет к значению NULL. Так что это ловится, получая дату created из таблицы task.

Вторая часть заключается в получении последней строки: здесь я получаю последнюю строку журнала по DISTINCT и ORDER BY assign_date DESC. Итак, я знаю последний assignee_to. Остальное аналогично первой части: получение resolved значения из таблицы задач.

ответил(а) 2018-12-11T18:09:00+03:00 1 год, 10 месяцев назад
Ваш ответ
Введите минимум 50 символов
Чтобы , пожалуйста,
Выберите тему жалобы:

Другая проблема