在没有任何内容的日子里加零

时间:2011-05-29 14:15:56

标签: sql sql-server-2008 date

此问题之前已经发布,但是,正确的答案似乎不起作用,所以我再次问它。

如果没有记录,此代码应返回最后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 个答案:

答案 0 :(得分:1)

由于您使用的是SQL Server 2008,因此可以尝试使用Common Table Expression (CTE)OUTER APPLY进行如下所述的操作。

Common Table Expressions可用于执行递归函数。在这种情况下,CTE将初始日期作为当前日期之前1个月的日期,然后通过添加1天递归循环,直到循环到达当前日期。因此,形成两个给定日期之间的日期列表。使用该CTE输出,我们可以使用OUTER APPLY来查找给定日期范围的经过持续时间的总和。

您还可以将CTE创建为表值函数,并使用它,如表值函数一节所示。下面提供的两个选项都是相同的,它们将功能略有不同。

屏幕截图# 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