2016-03-28 2 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) 

質問ならば、それはしませんが、月の28日は、すべての活動を持っていない、のは言わせ、ありますさえリストアップされます。しかし、私のチャートAPIのために、私はそれを列挙し、カウンタのために0で取得する必要があります。

明らかに、提案を受け入れる!

+7

何度も話し合った。カレンダーテーブルが必要です。その後、カレンダーテーブルを取得し、ACTIVITYに参加し、カレンダーテーブルのIDでグループ化します。 –

+0

もっと革新的なものを探していましたが、ありがとう! –

+1

これを処理するには、カレンダーテーブルまたは集計テーブルが最適です。他に何をするかわからないSQL Serverが1つを返す行がなければなりません。 –

答えて

3

すべての日付を含む表を作成します。次に、Activityテーブルを使用して左ジョインを行います。グループを日付に合わせ、Activity.idにCOUNTを入力してください。左結合により、結合節で一致しなくても、日付表のすべての日付が結果セットに含まれます。

+0

それは間違っているが、無意味な構造を作ることは悪い習慣です。アプリケーションのためには動作しますが、DBスキーマは失われます。私が上記のコメントで言ったように、私は質問だけでしかできないより革新的なソリューションを探していました。 –

+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

うーん、もしあなたが革新したいなら。ここでは、2つの手順は次のとおりです。

  • テーブルにフラグを追加活動が
  • 有効であるかどうかについては、これらの仕事をどのようにSQL Serverエージェントへ

を仕事を追加しますか?

alter table activity add column ActivityIsValid smallint default 1; 

このように、新しい行は無効な有効なアクティビティとして挿入されます。

そして、1日1回、次のコードを実行するために、SQL Serverエージェントジョブをスケジュール:

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

次に、あなたのようにクエリを実行することができます。これだけの作品は前進し、

もちろん
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); 

。履歴データに余分な行を手動で挿入することができます。

WHERE句の変更にも注意してください。直接の日付比較を行うことで、SQLエンジンはインデックスを利用することができます。

+0

InnovationがStack Overflowで匿名でdownvotedされましたか? –

+0

大文字/小文字のステートメントについて説明できますか?SUM(CASE WHEN ActivityIsValid = 1 THEN 1 ELSE 0 END) 1と0のときの和の結果は何ですか? – RGS

+1

これは 'ActivityIsValid'が' 1'の値をとる行の数を数えます。 –

関連する問題