2016-03-24 19 views
1

私はCOUNT()GROUP BYを使用して、先週の売上を示すグラフに値を設定しています。しかし、それは売り上げがある日だけを返し、売り上げはない日を返します。例えばSQL Server COUNT()とGROUP BY SQL Serverの戻り値を取得する2016

:私は週に完全な7日間埋めるために行が(原因その日なし販売に)戻されないされていると私はすべての日のために頼むUNIONをしようとしてきた

SELECT 
    DATEPART(DAY,DateSubmitted) AS DayOf, 
    COUNT(*) AS DayCount 
FROM 
    [User] 
WHERE 
    DATEPART(WEEK, getdate() -7) = DATEPART(WEEK, DateSubmitted) 
    AND YEAR(GETDATE()) = YEAR(DateSubmitted) 
GROUP BY 
    DATEPART(DAY, DateSubmitted) 

UNION ALL 

SELECT 
    DATEPART(DAY, DateSubmitted) AS DayOf, 
    COUNT(*) AS DayCount 
FROM 
    [User] 
WHERE 
    DATEPART(WEEK, getdate() -7) = DATEPART(WEEK, DateSubmitted) 
    AND YEAR(GETDATE()) = YEAR(DateSubmitted) 
    AND 'CODE HERE TO GET DAYS WHERE COUNT GETS NO RESULTS AND ASSIGN 0' 
GROUP BY 
    DATEPART(DAY, DateSubmitted) 

。私は、0以上のカウントに加えて、ゼロ/ヌルのカウントを行結果に付加するSQLを把握することができませんでした。下の結果は、先週の13日と19日のゼロ売上を含まないことがわかります。

私が今見る何を:

enter image description here

私が見たいもの:事前に

enter image description here

感謝を!

+0

行がない場合、行を返すことはできません。何をする必要があるのは、カウントクエリへの左結合を使って、別のテーブルをクエリの基本テーブルとして使用することです。他のデータがない場合、結果に行が表示されます。 –

+0

意味@SeanLangeになります。私は少し運があなたの応答の推論を理解することを試みた。 –

+0

これは、数値表または集計表の優れた用途の1つです。あなたのクエリは、あなたの日付をチェックする方法とは異なります。 –

答えて

1

をカウントする必要があるかもしれません日付。実際のトリックは、日付のリストに対して外部結合を使用して、あなたが望むゼロを与える一致を見つける結果を数えることです。

with dates as (
    select 
     cast(dateadd(day, n, 
      dateadd(day, -datepart(weekday, current_timestamp) - 6, current_timestamp) 
     ) as date) as DayOf 
    from (values (0), (1), (2), (3), (4), (5), (6)) m(n) 
) 
select dates.DayOf, count(u.DateSubmitted) as DayCount 
from dates left outer join [User] u on cast(u.DateSubmitted as date) = dates.DayOf 
group by dates.DayOf 

テーブルが大きく、列がインデックス化されている場合は、参加条件に日付範囲フィルタを追加することができます。

from dates left outer join [User] u on u.DateSubmitted = dates.DayOf 
    and u.DateSubmitted >= 
     cast(dateadd(day, -datepart(weekday, current_timestamp) - 6, current_timestamp) as date) 
    and u.DateSubmitted < 
     cast(dateadd(day, -datepart(weekday, current_timestamp) + 1, current_timestamp) as date) 

あなたはdatepart(week, ...を使用して注意してくださいしたいと思う)の先頭付近新年。私はあなたが1月1日から始まる部分的な週だけを見たいと思っているのか、前年の日数を含めたいのか分からない。

+0

この解決策にも近づきます。私は今、先週から7日間をすべて取得しますが、COUNTはすべての日でゼロです。それでも静止していません... –

+0

おそらく日付の問題です。 'cast(u.DateSubmitted as date)= dates.DayOf'を試してみてください。また、DayOfをCTEの日付にキャストするように編集しました。 – shawnt00

+1

あの男は最後に編集しました@ shawnt00!今私はあなたの例を使って作業コードを参照するために、テーブルの頭の中で同様の概念をどのように翻訳するかを学ぶ必要があります。 –

1

ここでは、このような種類のタリーテーブルを使用する例を示します。私は実際に私のシステム上のビューとして、この全体のセットを持っているので、私は何度もそれを書くことについて心配する必要はありません。また、Where述語を変更して、DateSubmitted列の索引付けを利用できるようにしました。

--EDIT--

WITH 
    E1(N) AS (select 1 from (values (1),(1),(1),(1),(1),(1),(1),(1),(1),(1))dt(n)), 
    E2(N) AS (SELECT 1 FROM E1 a, E1 b), --10E+2 or 100 rows 
    E4(N) AS (SELECT 1 FROM E2 a, E2 b), --10E+4 or 10,000 rows max 
    cteTally(N) AS 
    (
     SELECT ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) FROM E4 
    ) 

SELECT t.N AS DayOf 
    , COUNT(u.DateSubmitted) AS DayCount 
FROM cteTally t 
left join [User] u on t.N = DATEPART(DAY, DateSubmitted) 
WHERE DateSubmitted >= dateadd(week, datediff(week, 0, getdate()) - 1, 0) --Beginning of last week 
    AND DateSubmitted < dateadd(week, datediff(week, 0, getdate()), 0) --Beginning of this week 
GROUP BY t.N 

は、ここで私は私が私のシステム上でこれを行うだろうかを示します。最初に私はビューとして自分のcteTallyを作成します。これは私が常時使っているもので、読み込みがゼロの状態でほぼ即座に10,000行を生成します。

create View [dbo].[cteTally] as 

WITH 
    E1(N) AS (select 1 from (values (1),(1),(1),(1),(1),(1),(1),(1),(1),(1))dt(n)), 
    E2(N) AS (SELECT 1 FROM E1 a, E1 b), --10E+2 or 100 rows 
    E4(N) AS (SELECT 1 FROM E2 a, E2 b), --10E+4 or 10,000 rows max 
    cteTally(N) AS 
    (
     SELECT ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) FROM E4 
    ) 
select N from cteTally 
GO 

今実際の問題については、私はUserテーブルを作成します。この場合は、作業を簡単にするための一時テーブルを作成しました。

create table #User 
(
    DateSubmitted datetime 
) 

insert #User 
select '2016-03-14' union all 
select '2016-03-14' union all 
select '2016-03-15' union all 
select '2016-03-16' union all 
select '2016-03-17' union all 
select '2016-03-18'; 

サンプルと同じように、これには週の最初または最後の曜日のデータがありません。あなたが達成しようとしていることに合わせてクエリを少し調整する必要がありました。私の最初の投稿では、where節の日付チェックが間違っていました。これは、実際にはjoinをinner joinに変えました。私はそれらを結合述語に移動しました。これで、集計表を私たちが望む7日間に制限する必要があります。これは、DAYOFWEEK(u.DateSubmitted)を使用して達成できる他の方法がありますが、私はsargabilityを維持したいと思います。達成するために、where句にいくつかの条件を追加する必要がありました。

これはおそらく少し微調整することができますが、実際には先週の期待される結果が得られます。 1つの注意点は、もしあなたの先週が今年の終わりに及ぶならば、これに対応するために少し調整が必要ですが、大したことではないはずです。

SELECT t.N AS DayOf 
    , COUNT(u.DateSubmitted) AS DayCount 
FROM cteTally t 
left join #User u on t.N = DATEPART(DAY, DateSubmitted) 
AND DateSubmitted >= dateadd(week, datediff(week, 0, getdate()) - 1, 0) --Beginning of last week 
    AND DateSubmitted < dateadd(week, datediff(week, 0, getdate()), 0) --Beginning of this week 
where t.N >= DAY(dateadd(week, datediff(week, 0, getdate()) - 1, 0)) - 1 
    and t.N < day(dateadd(week, datediff(week, 0, getdate()), 0)) - 1 
GROUP BY t.N 
+0

私は 'count(u.DateSubmitted)'を使ってゼロを返す必要があると思います。 – shawnt00

+0

ああそうです。 Thanks @ shawnt00 –

+0

これは近づいていますが、必要な日付範囲は毎週日曜日から土曜日までです。それは、売上高がない(DateSubmitted datetimeフィールド)最後のカレンダーの週から2日間、「Date 13th Value 0」または「Date 19th Value = 0」がまだ得られていないと言いました。私はおそらくこの適切なコードからそれを動作させることができます。今しようとしています... –

1

ここで私はあなたのwhere句をオフに左例えば、いくつかの列名を構成した1から31までの数字のリストを生成するためにCTEを使用するための別のオプションですが、あなたはもちろんの集約一部を変更することができます必要に応じてクエリの

;with dates as (select 1 as number 
       union all 
       select number + 1 
       from dates 
       where number < 31) 


select a.number as DayOf, count(eventID) as DayCount from Dates a 
left join MyTable b 
on a.number = datepart(day, b.datesubmitted) 
group by a.number 
order by a.number 

SQLフィドル例http://sqlfiddle.com/#!6/93a0c/3

0
SELECT DATEPART(DAY, DateSubmitted) AS DayOf, 
     COUNT(CASE WHEN DATEPART(WEEK, getdate() -7) = DATEPART(WEEK, DateSubmitted) 
        then 1 ELSE 0 END 
      ) AS DayCount 
    FROM [User] 
WHERE YEAR(GETDATE()) = YEAR(DateSubmitted) 
GROUP BY DATEPART(DAY, DateSubmitted) 

あなたはおそらくのテーブルを生成するより複雑な方法のいくつかを使用する必要はありませんあなたは、限られた日数を扱っているので、SUMを使用するのではなく