добавить ноль для дней, в которых ничего нет - PullRequest
0 голосов
/ 29 мая 2011

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

Этот код должен возвращать последние 31 день с нулем, если нет записей;

   SELECT dates.Date as Dates, isnull(Sum(ElapsedTimeSeconds),0) as ElapsedSeconds
FROM 
[fnDateTable] (dateadd("m",-1,CONVERT(VARCHAR(10),GETDATE(),111)),CONVERT(VARCHAR(10),GETDATE(),111),'day') dates 
LEFT JOIN UsersApplog on dates.date = UsersAppLog.LoggedDate
group by Dates.Date

Смотрите [fnDateTable] здесь; fnDateTable

я получаю только строки, в которых есть данные. Очень надоедливый.

Спасибо за любую помощь, которую вы можете оказать. Я уверен, что это простое решение, но это вне меня.

Это какой-то вывод, где есть данные из userapplog;

Dates   ElapsedSeconds
2011-05-17 00:00:00.000 5854
2011-05-18 00:00:00.000 5864
2011-05-21 00:00:00.000 4758
2011-05-22 00:00:00.000 8434
2011-05-23 00:00:00.000 2162
2011-05-25 00:00:00.000 491
2011-05-26 00:00:00.000 260
2011-05-28 00:00:00.000 216

Если я бегу;

 SELECT dates.Date as Dates
   FROM 
   [fnDateTable] (dateadd("m",-   1,CONVERT(VARCHAR(10),GETDATE(),111)),CONVERT(VARCHAR(10),GETDATE(),111),'day') dates 

Я получаю

Dates
2011-04-29 00:00:00.000
2011-04-30 00:00:00.000
2011-05-01 00:00:00.000
2011-05-02 00:00:00.000
2011-05-03 00:00:00.000
2011-05-04 00:00:00.000
2011-05-05 00:00:00.000
.
.

1 Ответ

1 голос
/ 29 мая 2011

Поскольку вы используете 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:

data

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

Output

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...