Поскольку вы используете SQL Server 2008, вы можете попробовать что-то вроде описанного ниже, используя Common Table Expression (CTE)
и OUTER APPLY
.
Common Table Expressions
может использоваться для выполнения рекурсивных функций.В этом случае CTE принимает начальную дату за 1 месяц до текущей даты, а затем рекурсивно зацикливает, добавляя 1 день, пока цикл не достигнет текущей даты.Следовательно, формируется список дат между двумя указанными датами.Используя этот вывод CTE, мы можем использовать OUTER APPLY
, чтобы найти сумму прошедшей длительности для данного диапазона дат.
Вы также можете создать CTE как табличную функцию и использовать ее, как показано в разделе Табличная функция.Обе опции, представленные ниже, одинаковы и разделяют функциональные возможности немного по-разному.
Screenshot # 1 показывает пример данных, хранящихся в таблице dbo.UsersAppLog и снимке экрана # 2 отображает вывод.Вывод будет одинаковым при использовании обоих подходов, потому что единственное различие между приведенными ниже опциями заключается в том, что один из них имеет часть логики, перемещенную в функцию..
Option #1
Желаемый вывод без использования табличной функции:
DECLARE @BeginDate DATETIME;
DECLARE @EndDate DATETIME;
SET @BeginDate = DATEADD(MONTH, -1, GETDATE());
SET @EndDate = GETDATE();
WITH CTE(DateRange) AS
(
SELECT @BeginDate AS DateRange
UNION ALL
SELECT DATEADD(DAY, 1, DateRange)
FROM CTE
WHERE DATEADD(DAY, 1, DateRange) <= @EndDate
)
SELECT DATEADD(DAY, 0, DATEDIFF(DAY, 0, CTE.DateRange)) AS DateRange
, COALESCE(UAL.ElapsedDuration, 0) AS ElapsedDuration
FROM CTE
OUTER APPLY (
SELECT SUM(ElapsedSeconds) ElapsedDuration
FROM dbo.UsersAppLog UAL
WHERE DATEDIFF(DAY, UAL.LoggedDate, CTE.DateRange) = 0
) UAL;
Option #2
Создать скрипт для функции с табличным значением: .
CREATE FUNCTION [dbo].[fntDateRange]
(
@BeginDate DATETIME
, @EndDate DATETIME
)
RETURNS TABLE
AS
RETURN
(
WITH CTE(DateRange) AS
(
SELECT @BeginDate AS DateRange
UNION ALL
SELECT DATEADD(DAY, 1, DateRange)
FROM CTE
WHERE DATEADD(DAY, 1, DateRange) <= @EndDate
)
SELECT DATEADD(DAY, 0, DATEDIFF(DAY, 0, CTE.DateRange)) AS DateRange
FROM CTE
)
GO
Требуемый вывод с использованием функции с табличным значением: .
SELECT RNG.DateRange
, COALESCE(UAL.ElapsedDuration, 0) AS ElapsedDuration
FROM dbo.fntDateRange(DATEADD(MONTH, -1, GETDATE()), GETDATE()) RNG
OUTER APPLY (
SELECT SUM(ElapsedSeconds) ElapsedDuration
FROM dbo.UsersAppLog UAL
WHERE DATEDIFF(DAY, UAL.LoggedDate, RNG.DateRange) = 0
) UAL;
Надеюсь, это поможет.
Снимок экрана № 1:

Снимок экрана #2:
