#datetime #reporting-services
#дата и время #отчеты-службы
Вопрос:
У меня есть отчет, который я создал с помощью SSRS. В настоящее время он извлекает дату и время для последнего ввода, полученного на компьютере. Моя цель — найти самое длительное время простоя компьютера. У меня есть данные, но просто нужно выяснить, как их логически извлечь.
Вот скриншот примера данных: (https://i.stack.imgur.com/jRFs4.png )
Исходя из этого, я мог бы сказать, что наибольшая продолжительность простоя компьютера составит 3 дня 19-го числа. Любая помощь приветствуется!
Редактировать:
Ниже приведен мой запрос для моего исходного набора данных:
Select
a.Name0 AS [Computer Name],
b.LastKeyInput0 AS [Last Input Time]
From
v_R_System a
Inner Join
v_HS_UHHG640 b
on b.ResourceID = a.ResourceID
where a.Name0 = @ComputerName
Этот запрос вернет компьютер и историю его простоев, как указано ниже:
Результаты конструктора запросов
Вопрос: Как мне связать ваше решение с этим запросом? СПАСИБО ЗА ВАШУ ПОМОЩЬ!
Ответ №1:
Я скопировал ваши данные для этого примера. Я не уверен, что вы хотите в своем конечном выводе, но этого будет достаточно, чтобы продолжить. Этот ответ довольно длинный, поскольку я пытался объяснить каждый шаг. В конечном итоге вы могли бы удалить половину кода, но его постепенное построение помогает понять. Если вы хотите просто просмотреть окончательный запрос, перейдите к биту с надписью «Наконец:» ниже
Чтобы создать ваши данные, я просто сделал следующее
DECLARE @t TABLE(LastInputTime datetime)
INSERT INTO @t VALUES
('2020-09-18 11:13'),
('2020-09-19 12:58'),
('2020-09-19 12:58'),
('2020-09-19 12:58'),
('2020-09-22 11:32'),
('2020-09-23 10:12'),
('2020-09-24 11:51')
Затем мы можем отобразить эти данные и данные предыдущих строк, используя функцию ЗАДЕРЖКИ.
SELECT
*
, PreviousDateTime = LAG(LastInputTime, 1, LastInputTime) OVER(ORDER BY LastInputTime)
FROM @t
LAG()
Функция здесь получает столбец LastInputTime из строки с задержкой 1 (предыдущая строка). Если строка не найдена, 3-й аргумент говорит, вместо этого верните значение текущей строки. Это значение по умолчанию просто делает следующий бит более чистым.
Мы получаем следующие результаты, поскольку вы можете видеть, что PreviousDateTime показывает предыдущую строку (за исключением первой строки, где предыдущей строки не существует).
Теперь у нас есть данные предыдущей строки, мы можем использовать их для вычисления времени между двумя значениями с
IdleTimeInSeconds = DATEDIFF(s, LAG(LastInputTime, 1, LastInputTime) OVER(ORDER BY LastInputTime), LastInputTime)
Здесь мы используем DATEDIFF()
и получаем количество секунд ( s
), начиная с предыдущего времени ожидания (функция задержки выхода) и заканчивая последним временем ввода.
Итак, наш запрос теперь выглядит следующим образом…
SELECT
*
, PreviousDateTime = LAG(LastInputTime, 1, LastInputTime) OVER(ORDER BY LastInputTime)
, IdleTimeInSeconds = DATEDIFF(s, LAG(LastInputTime, 1, LastInputTime) OVER(ORDER BY LastInputTime), LastInputTime)
FROM @t
Теперь, сохраняя простоту, мы можем использовать это как подзапрос и получить верхнюю 1 строку, упорядоченную по IdleTimeInSeconds в порядке убывания. Мы можем обернуть результат в текст, чтобы он имел больше смысла в отчете.
Наконец:
Это последний запрос, который вы можете выполнить для тестирования, поскольку он не требует фактических данных
DECLARE @t TABLE(LastInputTime datetime)
INSERT INTO @t VALUES
('2020-09-18 11:13'),
('2020-09-19 12:58'),
('2020-09-19 12:58'),
('2020-09-19 12:58'),
('2020-09-22 11:32'),
('2020-09-23 10:12'),
('2020-09-24 11:51')
SELECT top 1
*
, Message = 'Longest idle time was '
CAST(IdleTimeInSeconds as varchar(20))
' seconds, from '
CAST(LAG(LastInputTime, 1, LastInputTime) OVER(ORDER BY LastInputTime) as varchar(20))
' to '
CAST(LastInputTime as varchar(20))
FROM (
SELECT
*
, PreviousDateTime = LAG(LastInputTime, 1, LastInputTime) OVER(ORDER BY LastInputTime)
, IdleTimeInSeconds = DATEDIFF(s, LAG(LastInputTime, 1, LastInputTime) OVER(ORDER BY LastInputTime), LastInputTime)
FROM @t
) x ORDER BY IdleTimeInSeconds DESC
Это дает следующий результат.
Обновить
На основе предоставленного вами запроса окончательный запрос будет выглядеть следующим образом…
SELECT TOP 1
*
, Message = 'Longest idle time was '
CAST(IdleTimeInSeconds as varchar(20))
' seconds, from '
CAST(LAG([Last Input Time], 1, [Last Input Time]) OVER(ORDER BY [Last Input Time]) as varchar(20))
' to '
CAST([Last Input Time] as varchar(20))
FROM (
SELECT
a.Name0 AS [Computer Name],
b.LastKeyInput0 AS [Last Input Time],
PreviousDateTime = LAG(b.LastKeyInput0, 1, b.LastKeyInput0) OVER(ORDER BY b.LastKeyInput0),
, IdleTimeInSeconds = DATEDIFF(s, LAG(b.LastKeyInput0, 1, b.LastKeyInput0) OVER(ORDER BY b.LastKeyInput0), b.LastKeyInput0)
FROM v_R_System a
JOIN v_HS_UHHG640 b on b.ResourceID = a.ResourceID
WHERE a.Name0 = @ComputerName
) x ORDER BY IdleTimeInSeconds DESC
Комментарии:
1. Это хорошо написано и прекрасно работает! Большое вам спасибо! Единственная проблема, с которой я сейчас сталкиваюсь, — это перенос моих данных из табликса SSRS в таблицу, которую вы объявляете в своем коде. Должен ли я создать второй набор данных для этого или как-то добавить его в исходный запрос набора данных? Снова.. Спасибо!
2. Это зависит от того, как выглядит ваш текущий запрос к набору данных. Вы должны быть в состоянии интегрировать свой код в метод, который я описал. Обновите ваш вопрос и покажите ваш текущий запрос, и я постараюсь помочь.
3. Я обновил исходный вопрос с объяснением и запросом. Спасибо!
4. Я обновил ответ, включив в него исходный код, вы увидите, что особых изменений не требуется, просто добавив пару вычисляемых столбцов и изменив несколько имен столбцов. Если это ответ на ваш вопрос, пожалуйста, отметьте ответ как принятый. Спасибо.