当没有数据存在SQL Server时显示月份值

时间:2016-04-25 15:54:20

标签: sql sql-server datetime

我有一个SQL Server 2012表,其中包含每个用户的会话数,我需要找出每月活动的总分钟数,如果该月没有结果,则显示“0”。下表:

User   SessionStart              SessionEnd
1      2014-03-01 08:00:00.000   2014-03-01 08:10:00.000
1      2014-03-15 09:00:00.000   2014-03-15 09:30:00.000
1      2014-05-01 04:00:00.000   2014-05-01 04:50:00.000
1      2014-06-01 02:00:00.000   2014-06-01 02:05:00.000
1      2014-07-01 09:00:00.000   2014-07-01 10:30:00.000
1      2014-09-01 01:00:00.000   2014-09-01 01:07:00.000
1      2014-12-05 08:00:00.000   2014-12-05 08:10:00.000
2      2014-01-01 01:01:00.000   2014-01-01 01:11:00.000
1      2015-03-01 08:00:00.000   2015-03-01 08:10:00.000
1      2015-05-01 04:00:00.000   2015-05-01 04:50:00.000
1      2015-06-01 02:00:00.000   2015-06-01 02:05:00.000
...    ...                       ...

我最终得到的是:

User   Month   Year   Minutes 
1      3       2014   40
1      5       2014   50  
1      6       2014   5
1      7       2014   90
1      9       2014   7
1      12      2014   10
1      3       2015   10
1      5       2015   50
1      6       2015   5

我想得到什么:

User   Month   Year   Minutes 
1      1       2014   0
1      2       2014   0
1      3       2014   40
1      4       2014   0
1      5       2014   50  
1      6       2014   5
1      7       2014   90
1      8       2014   0
1      9       2014   7
1      10      2014   0
1      11      2014   0
1      12      2014   10
1      1       2015   0
1      1       2015   0
1      3       2015   10
1      4       2015   0
1      5       2015   50
1      6       2015   5

我尝试过使用:

SELECT User
      ,MONTH(SessionStart)
      ,YEAR(SessionStart)
      ,SUM(DATEDIFF(minute, SessionStart, SessionEnd)) AS Minutes
FROM SessionTable
WHERE User = 1 AND YEAR(SessionStart) >= 2014
GROUP BY SessionStart, User

我有一个名为“Months”的表,它保存月份(月份)和月份名称(MonthName),并尝试在此表上执行左外连接,并尝试使用案例选择。我在Stackoverflow上搜索了这个问题,看到了一些类似的问题,但没有涉及使用日期的问题。今天苦苦思索......

3 个答案:

答案 0 :(得分:3)

您可以使用cross join生成所有行,然后使用left join来引入摘要。假设每个月存在一些行,您可以从会话表本身获取此信息:

SELECT u.User, yyyymm.mm, yyyymm.yy
       COALESCE(SUM(DATEDIFF(minute, s.SessionStart, s.SessionEnd)), 0) AS Minutes
FROM (SELECT 1 as user) u CROSS JOIN
     (SELECT DISTINCT YEAR(SessionStart) as yyyy, MONTH(SessionStart) as mm
      FROM SessionTable
      WHERE SessionStart >= '2014-01-01'
     ) yyyymm LEFT JOIN
     SessionStart ss
     ON u.user = ss.user AND
        YEAR(SessionStart) = yyyymm.yy AND MONTH(SessionStart) = yyyymm.mm
GROUP BY u.User, yyyymm.yyyy, yyyymm.mm;

答案 1 :(得分:1)

您使用months表格走在正确的轨道上。您可以使用左外连接发布您的示例吗?如果您从months开始并将外部联接留给SessionTable,那么您应该没问题。

像...一样的东西。

SELECT User
      ,MONTH(m.month)
      ,YEAR(m.year)
      ,SUM(DATEDIFF(minute, s.SessionStart, s.SessionEnd)) AS Minutes
FROM Months m
  LEFT OUTER JOIN SessionTable s
    ON m.year = s.year
    AND m.month = s.month
    AND s.User = 1 
WHERE YEAR(m.year) >= 2014
GROUP BY s.SessionStart, s.User

注:

  • 当您使用sessionTable作为主要数据源时,请勿过滤where子句中的month数据 - 在LEFT OUTER JOIN中对其进行过滤。如果您将其放在WHERE中,则会将事情变为INNER JOIN
  • 您希望在返回月/年信息数据时使用months表格

那工作?

答案 2 :(得分:0)

您需要有一个日历表,通常是在某个范围内的预定义日期列表..

您需要有月表来满足您的需求......可以使用数字表生成..

这只是伪代码:

create table months
(
monthdate datetime
)

insert into monthdate
select dateadd(day,n,getdate()-10000)
from numbers
where n<=10000

现在你有月份表,你需要做的就是左连接

select *
from monthstable mt
join yourtable yt
on yt.date=mt.date

这样你就可以保留你没有的所有日期

**一些好的链接:**
 http://www.sqlservercentral.com/blogs/dwainsql/2014/03/30/calendar-tables-in-t-sql/

http://www.sqlservercentral.com/articles/T-SQL/62867/