2012-04-04 183 views
0

沒有記錄在給定月份,我有以下一組數據:在SQL COUNT和GROUP BY月

ID | CREATED  | USER 
-------------------------- 
1 | 2012-01-14 | XYZ 
2 | 2012-03-14 | XYZ 
3 | 2012-03-15 | XYZ 
4 | 2012-03-24 | ABC 
5 | 2012-04-10 | XYZ 
6 | 2012-04-11 | ABC 

我需要一個報告,它顯示給定用戶,但也與計數0個月沒有記錄的地方。

MTH | COUNT 
------------- 
JAN | 1 
FEB | 0 
MAR | 2 
APR | 1 

我設法讓它工作,但沒有記錄的月份沒有0。到目前爲止,我有這個語法是拋出一個錯誤..

SELECT Month(CREATED), COUNT(SELECT * FROM SEARCHES WHERE USER = 'XYZ') 
FROM SEARCHES 
GROUP BY Month(CREATED) 

回答

1

下面是按日期範圍編組通用查詢。 @startDate和@endDate定義了範圍;你可以爲用戶設置min(創建)和max(創建),或者設置一些固定的範圍。

CTE monthlyRange生成月表 - 當月的第一個月,下個月的第一個月。搜索稍後通過創建而加入到MonthlyRanges中。請注意,用戶在連接中被過濾,因爲這是左連接,並且在where子句中進行篩選將有效地將其轉換爲內連接。

declare @startDate datetime 
declare @endDate datetime 
set @startDate = '2012-01-01' 
set @endDate = '2013-01-01' 

; with monthlyRange (startMonth, startNextMonth) as (
    select dateadd (m, datediff (m, 0, @startDate), 0), 
     dateadd (m, datediff (m, 0, @startDate) + 1, 0) 
    union all 
    select dateadd (m, 1, startMonth), 
     dateadd (m, 1, startNextMonth) 
    from monthlyRange 
    where startNextMonth <= dateadd (m, datediff (m, 0, @endDate), 0) 
) 
SELECT Year(monthlyRange.startMonth) Year, 
     Month(monthlyRange.startMonth) Month, 
     COUNT(searches.Created) Count 
    FROM monthlyRange 
    left join SEARCHES 
    on monthlyRange.startMonth <= Searches.Created 
    and monthlyRange.startNextMonth > Searches.Created 
    and [USER] = 'XYZ' 
GROUP BY Year(monthlyRange.startMonth), Month(monthlyRange.startMonth) 
order by 1, 2 

Here is Sql Fiddle for testing

+0

這個工作太棒了!也感謝您向我介紹SQL小提琴。 – greener 2012-04-05 17:34:04

2

你不能查詢不存在的數據。所以你需要加入表格,列出(或模擬列表)你想加入的所有月份。如何做到這一點可以取決於你正在使用的rdbms。使用rownum生成可以轉換爲月份的列表是常用的方法。或者Postgres有一個函數來生成一個系列。另外,我不明白爲什麼子選擇在列子句中,而不是將過濾器添加到主查詢中。

參見:

SQL frequency distribution query to count ranges with group-by and include 0 counts

How to generate list of all dates between sysdate-30 and sysdate+30?

0

試試這個:

CREATE TABLE #DaTable(
    ID INT, 
    CREATED DATE, 
    USER_ VARCHAR(10) 
) 
INSERT INTO #DaTable(ID, CREATED, USER_) VALUES 
(1 , '2012-01-14', 'XYZ'), 
(2 , '2012-03-14' , 'XYZ'), 
(3 , '2012-03-15' , 'XYZ'), 
(4 , '2012-03-24' , 'ABC'), 
(5 , '2012-04-10' , 'XYZ'), 
(6 , '2012-04-11' , 'ABC') 

CREATE TABLE #DaMonths(
    Nr INT, 
    Name VARCHAR(10) 
) 
INSERT INTO #DaMonths(Nr, Name) VALUES 
(1, 'Jan'), 
(2, 'Feb'), 
(3, 'Mar'), 
(4, 'Apr'), 
(5, 'May'), 
(6, 'Jun'), 
(7, 'Jul'), 
(8, 'Aug'), 
(9, 'Sep'), 
(10, 'Oct'), 
(11, 'Nov'), 
(12, 'Dec') 

SELECT M.Nr, M.Name, COUNT(DT.ID) as Count_ 
FROM #DaMonths as M 
    LEFT OUTER JOIN #DaTable as DT ON 
    M.Nr = Month(DT.CREATED) 
GROUP BY M.Nr, M.Name 
ORDER BY M.Nr