Вопрос или проблема
Я пытаюсь разбить записи на части по machine_id и process_id, а затем обработать их.
WITH table_partition_by_machine_id AS
(
SELECT
*,
DENSE_RANK() OVER (PARTITION BY machine_id
ORDER BY Process_id, activity_type DESC) AS arrange_data
FROM Activity
),
-- создание столбца для нахождения разницы
previous_time_stamp AS
(
SELECT
*,
LAG(timestamp, 1) OVER (PARTITION BY machine_id) AS start_timestamp
FROM
table_partition_by_machine_id
),
-- нахождение общего времени каждого процесса на машине
process_time AS
(
SELECT
*,
timestamp - start_timestamp AS process_time
FROM
previous_time_stamp
WHERE
activity_type="end"
)
-- нахождение среднего времени всех процессов каждого устройства
SELECT
*,
AVG(process_time) OVER (PARTITION BY machine_id) processing_time
FROM
process_time
Этот запрос возвращает правильное среднее значение (processing_time
):
SELECT
*,
AVG(process_time) OVER (PARTITION BY machine_id) processing_time
FROM
process_time,
Правильный вывод:
machine_id | process_id | activity_type | timestamp | arrange_data | start_timestamp | process_time | processing_time |
---|---|---|---|---|---|---|---|
0 | 0 | end | 40.222 | 2 | 37.019 | 3.203000000000003 | 11.205000000000002 |
0 | 1 | end | 38.098 | 4 | 18.891 | 19.207 | 11.205000000000002 |
1 | 0 | end | 81.874 | 2 | 25.135 | 56.73899999999999 | 61.842999999999996 |
1 | 1 | end | 90.302 | 4 | 23.355 | 66.947 | 61.842999999999996 |
Но: эти запросы возвращают неправильное среднее значение:
SELECT
machine_id,
AVG(process_time) OVER (PARTITION BY machine_id) processing_time
FROM
process_time,
---
SELECT
machine_id,
AVG(process_time) processing_time
FROM
process_time,
GROUP BY
machine_id
Неправильный вывод:
machine_id | processing_time |
---|---|
0 | 1.602 |
1 | -8.428 |
Ответ или решение
Конечно! Давайте подробно разберем, как реализовать решение для задачи "1661. Среднее время процесса на машине" с использованием оконных функций и CTE (Common Table Expressions) в SQL.
Задача
Вам необходимо вычислить среднее время обработки (processing time
) для каждого machine_id
на основе данных, хранящихся в таблице Activity
, которая включает в себя такие поля, как machine_id
, process_id
, activity_type
и timestamp
.
Подход
Мы использовали три CTE для обработки данных:
-
table_partition_by_machine_id
: Этот CTE позволяет нам порядково распределить записи для каждой машины с использованием функцииDENSE_RANK()
поprocess_id
иactivity_type
. -
previous_time_stamp
: Здесь мы используем функциюLAG()
, чтобы получить предыдущую метку времени (timestamp
) для каждой машины, тем самым позволяя нам вычислить длительности процессов. -
process_time
: В этом CTE мы вычисляемprocess_time
для каждой записи, когдаactivity_type
равен "end", то есть, рассчитываем разницу междуtimestamp
иstart_timestamp
.
Ниже находится полностью реализованный SQL-запрос:
WITH table_partition_by_machine_id AS
(
SELECT
*,
DENSE_RANK() OVER (PARTITION BY machine_id
ORDER BY process_id, activity_type DESC) AS arrange_data
FROM Activity
),
-- Создание колонки для поиска разницы
previous_time_stamp AS
(
SELECT
*,
LAG(timestamp, 1) OVER (PARTITION BY machine_id ORDER BY timestamp) AS start_timestamp
FROM
table_partition_by_machine_id
),
-- Вычисление времени каждого процесса для машины
process_time AS
(
SELECT
*,
timestamp - start_timestamp AS process_time
FROM
previous_time_stamp
WHERE
activity_type = 'end'
)
-- Вычисление среднего времени для процессов каждой машины
SELECT
machine_id,
AVG(process_time) AS processing_time
FROM
process_time
GROUP BY
machine_id
Объяснение
-
DENSE_RANK()
: позволяет нам разбивать записи на группы в зависимости отmachine_id
и сортирует их поprocess_id
иactivity_type
. -
Функция
LAG()
: обеспечивает возможность получения предыдущего значенияtimestamp
в пределах группы, чтобы затем можно было рассчитывать разницу времени. Это позволяет нам узнать, сколько времени длился процесс. -
Фильтрация по
activity_type
: Мы отбираем только те записи, которые имеютactivity_type
равный "end", поскольку именно это указывает на завершение процесса. -
Результативный запрос: мы группируем по
machine_id
и вычисляем среднее время обработки всех процессов для каждой машины.
Заключение
Этот подход с использованием CTE и оконных функций позволяет эффективно вычислять средние значения и обеспечивает гибкость в обработке данных. Если возникнут ошибки, важно проверить порядок операций и убедиться, что функции окон используются правильно и логика вычислений верна.