2016-04-25 68 views
1

我有一个SQL Server 2012表,每个用户持有会话,我需要找出活动的每月总分钟数,如果没有月结果,则显示“0 ”。如下表:显示不存在数据时的月份值SQL Server

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”的表格,其中保存了t他月(Month)和月份名称(MonthName),并尝试在此表上执行左外连接,并尝试使用大小写选择。我在Stackoverflow上搜索了这个问题,看到了一些类似的问题,但没有涉及到使用日期。今天努力思考......

+0

您是否尝试从'Months'表中选择,然后对'SessionTable'使用'LEFT OUTER JOIN'(一个表名,IMO - 当然是一个“表”)? –

回答

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; 
+0

到目前为止,这就像一个冠军。我确实有成千上万的行,并且能够从本身拉出年/月。从来没有想过这样的事情!我改变了一些变数,并且完全按照我希望的方式拉动...... –

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 

注:

  • 当你使用month为主要数据源,不要在where子句中筛选sessionTable数据 - 过滤它LEFT OUTER JOIN。如果你把它放在WHERE中,你就把它变成了INNER JOIN
  • 你想返回月/年信息

这项工作数据时使用您的months表?

+0

不幸的是,我没有列出上述年份的表格。在你的例子中,你有我在“月”表上匹配几年。使用你的例子,我仍然可以在没有我想拥有“0”的月份的情况下返回数据。我可能还需要创建多年的另一张桌子。 –

0

你需要有这通常是在一定范围内的预定义日期列表日历表..

你需要有个表,您可以need..which使用数字表生成..

这只是一个伪代码:

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/

相关问题