2016-03-28 57 views
0

因此,我正在统计系统中用户的活动记录。我得到的每一天中的某个月份和年份的活动计数器,就像下面的查询在没有记录的日期获得“零”计数

SELECT CONVERT(date, VIS_DATETIME) AS DATETIME, COUNT(*) AS ACTIVITY 
FROM ACTIVITY 
WHERE DATEPART(year, VIS_DATETIME) = 2016 AND 
     DATEPART(month, VIS_DATETIME) = 3 
GROUP BY CONVERT(date, VIS_DATETIME) 
ORDER BY CONVERT(date, VIS_DATETIME) 

的问题是,如果我们说,3月28日没有任何活动,也不会甚至被列出。但是,对于我的图表API,我需要获得该列表并使用0作为柜台。

很明显,接受建议!

+7

多次讨论。你应该有一些日历表。然后你拿日历表,并在ACTIVITY上进行左连接,按日历表的ID进行分组。 –

+0

正在寻找更具创新性的东西,但谢谢! –

+1

日历表或记事表是处理此问题的最佳方法。不知道你会做什么。 sql server必须有一行才能返回一个。 –

回答

3

创建一个包含所有日期的表。然后使用Activity表进行左连接。在日期上分组,并在Activity.id上执行COUNT。左连接确保来自日期表的所有日期都包含在结果集中,即使它们在连接子句中不匹配。

+0

不是说这是错误的,但创建无意义的结构是一种不好的做法。适用于应用程序,但废弃了数据库模式。就像我在上面的评论中所说的那样,我一直在寻找一种更具创新性的解决方案,只有通过查询才能做到。 –

+2

这不是一个没有意义的结构。这是一个使用统计表的好地方。 –

+1

所有的日期表是非常有用的,而不是一个毫无意义的结构。为什么要创造更具创新性的解决方案? :) – Arvo

3
Declare @DayOfMonth TinyInt Set @DayOfMonth = 1 
Declare @Month TinyInt Set @Month = 1 
Declare @Year Integer Set @Year = 2016 
Declare @startDate datetime 
Declare @endDate datetime 
-- ------------------------------------ 
Select @startDate = DateAdd(day, @DayOfMonth - 1, 
      DateAdd(month, @Month - 1, 
       DateAdd(Year, @Year-1900, 0))) 

select @endDate = dateadd(month,1,@startDate) 

;with dateRange as 
(
    select dt = dateadd(dd, 0, @startDate) 
    where dateadd(dd, 0, @startDate) < @endDate 
    union all 
    select dateadd(dd, 1, dt) 
    from dateRange 
    where dateadd(dd, 1, dt) < @endDate 
) 
select * 
from dateRange 

上述查询给出了月所有的日期,你可以留下你的聚合的查询与零计数得到的条目加入。

0

嗯,如果你想创新。这里有两个步骤:

  • 表中添加标记有关活动是否有效
  • 中添加作业到SQL Server代理

如何做这些工作?

alter table activity add column ActivityIsValid smallint default 1; 

这样,新行作为有效活动进入,而不是无效。

然后安排一个SQL Server代理作业每天运行一次下面的代码:

SELECT CONVERT(date, VIS_DATETIME) AS DATETIME, 
     SUM(CASE WHEN ActivityIsValid = 1 THEN 1 ELSE 0 END) AS ACTIVITY 
FROM ACTIVITY 
WHERE VIS_DATETIME >= '2016-03-01' AND 
     VIS_DATETIME < '2016-04-01   
GROUP BY CONVERT(date, VIS_DATETIME) 
ORDER BY CONVERT(date, VIS_DATETIME); 

当然,这只能前进:

insert into activity(vis_datetime, ActivityIsValid) 
    values(cast(getdate() as date), 0); 

然后,你可以为运行查询。您可以手动在历史数据中插入额外的行。

另请注意对WHERE条款的更改。通过进行直接日期比较,SQL引擎可以使用索引。

+0

创新现在匿名低于Stack Overflow? –

+0

您可以解释关于总和内的case语句,即SUM(CASE WHEN ActivityIsValid = 1 THEN 1 ELSE 0 END)。 1和0时和的结果是什么? – RGS

+1

计算'ActivityIsValid'对'1'的值所占的行数。 –

相关问题