2012-04-04 136 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