1

我有以下一组数据:

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

我需要一份报告,显示给定用户的 COUNT,但在没有记录的月份中显示 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)
4

3 回答 3

2

您无法查询不存在的数据。因此,您需要加入列出(或模拟列出)您想要加入的所有月份的表。如何做到这一点取决于您使用的 rdbms。使用 rownum 生成可以转换为月份的列表是一种常见的方法。或者 Postgres 具有生成系列的功能。顺便说一句,我真的不明白为什么子选择在列子句中而不是将过滤器添加到主查询中。

也可以看看:

SQL 频率分布查询使用 group-by 计算范围并包括 0 个计数

如何生成 sysdate-30 和 sysdate+30 之间的所有日期列表?

于 2012-04-04T22:29:37.487 回答
2

这是按日期范围分组的一般查询。@startDate 和 @endDate 定义范围;您可以为用户或某个固定范围设置 min(created) 和 max(created)。

CTE 每月范围生成月份表 - 本月的第一天,下个月的第一天。Searches 稍后通过创建左连接到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

这是用于测试的 Sql Fiddle

于 2012-04-04T23:05:59.120 回答
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
于 2012-04-04T23:03:27.843 回答