不活动天数的SQL日期行

时间:2010-04-22 18:16:03

标签: sql gaps-and-islands

假设这个表存储了每天的访问者数量。

当我想查询表格并从中创建图表时,会出现问题。

没有活动的日子在桌子上没有相应的行。

例如

Day1 - 7
Day2 - 8
Day4 - 7

生成的图表不正确。因为Day3需要0。

现在,如果不使用SQL以外的任何东西,可以为不活动日创建这些值吗?

我想创建另一个表,它会在每次执行脚本时创建30天的所有日期,并且问题已得到修复,但我想知道是否有更实际的解决方案。

提前致谢。

4 个答案:

答案 0 :(得分:1)

使用30天创建表格的解决方案是一个非常简单实用的解决方案。

如果你真的想要,你可以在没有额外桌子的情况下进行,但这并不令人愉快。 SQL实际上并不是为了允许您选择数据库中不存在的数据而设计的。一般来说,更简单的解决方案是在客户端添加缺少的行,而不是尝试编写复杂的SQL语句来执行此操作。

答案 1 :(得分:1)

使用Sql Server 2005+和CTE Recursive(Using Common Table Expressions),您可以尝试

DECLARE @Table TABLE(
        DateVal DATETIME,
        Visists INT
)

INSERT INTO @Table SELECT '01 Jan 2010', 10
INSERT INTO @Table SELECT '03 Jan 2010', 1
INSERT INTO @Table SELECT '05 Jan 2010', 30
INSERT INTO @Table SELECT '10 Jan 2010', 50

;WITH MinMax AS (
        SELECT  MIN(DateVal) Startdate,
                MAX(DateVal) EndDate
        FROM    @Table
),
DateRange AS(
        SELECT  StartDate DateVal
        FROM    MinMax
        UNION ALL
        SELECT  DateRange.DateVal + 1
        FROM    DateRange,
                MinMax
        WHERE   DateRange.DateVal + 1 <= MinMax.EndDate
)
SELECT  DateRange.DateVal,
        ISNULL(t.Visists,0) TotalVisits
FROM    DateRange LEFT JOIN
        @Table t ON DateRange.DateVal = t.DateVal

输出为

DateVal                 TotalVisits
----------------------- -----------
2010-01-01 00:00:00.000 10
2010-01-02 00:00:00.000 0
2010-01-03 00:00:00.000 1
2010-01-04 00:00:00.000 0
2010-01-05 00:00:00.000 30
2010-01-06 00:00:00.000 0
2010-01-07 00:00:00.000 0
2010-01-08 00:00:00.000 0
2010-01-09 00:00:00.000 0
2010-01-10 00:00:00.000 50

答案 2 :(得分:1)

我不会只调用这个SQL,因为它使用了PostgreSQL特定的函数 - 但是在你使用的数据库中可能会有类似的东西。

PostgreSQL有一个很好的功能:generate_series

您可以使用此功能创建30天的系列。

select current_date + s.a as dates from generate_series(0,30) as s(a);

 dates    
------------
 2010-04-22
 2010-04-23
 2010-04-24
 (.. etc ..)

然后,您可以在查询中使用它,例如:

select vpd.visits, temp.dates
  from (select current_date + s.a as dates from generate_series(0,30) as s(a)) as temp
 left outer join visits_per_day vpd on vpd.day = temp.dates

 visits |   dates    
--------+------------
     10 | 2010-04-22
        | 2010-04-23
     20 | 2010-04-24
        | 2010-04-25
        | 2010-04-26
     30 | 2010-04-27

答案 3 :(得分:0)

不,没有标准方法只使用SQL在SQL查询结果中添加不确定数量的缺失行而不先将这些行存储在表中。

您可以拥有一个包含应用程序运行日期的单个表,也可以使用一个表,只放置当前查询将使用的日期。如果您选择第二个解决方案,请记住计划同时执行具有不同日期范围的同一查询的不同用户 - 如果您的DBMS支持该表,您将希望该表是临时的和用户特定的。