2016-04-25 17 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 

私は、月の数を保持する "月"と呼ばれるテーブルを持っています彼の月(月)と月の名前(MonthName)を入力して、このテーブルに対して左外部結合を実行しようとしました。また、大文字と小文字の選択も試みました。私はこの問題をStackoverflowで検索し、やや似たような問題を見てきましたが、日付を使用する問題はありません。今日考えて苦労しています...

+0

'Months'テーブルから選択してみてください、その後、あなたの' SessionTable'に 'LEFT OUTER JOIN'を使用していましたか? –

答えて

3

cross joinですべての行を生成してから、left joinを使用してサマリーを表示できます。あなたのmonthsテーブルで正しい軌道に乗っている

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で始まり、外部への参加が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 JOINWHEREに入れると、INNER JOINになります。
  • あなたは月/年先の仕事

のためにあなたのデータを返すときに、あなたのmonthsテーブルを使用したいですか?

+0

残念ながら、私はリストされた年のテーブルを持っていない。あなたの例では、 "Months"テーブルで年を合わせています。あなたの例を使っても、私は月のないデータが返ってきて、 "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/

あなたは(IMO、テーブルの悪い名前 - もちろんそれは「テーブル」です)210

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

関連する問題