Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/77.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
SQL COUNT和GROUP BY month中没有给定月份的记录_Sql_Gaps And Islands - Fatal编程技术网

SQL COUNT和GROUP BY month中没有给定月份的记录

SQL COUNT和GROUP BY month中没有给定月份的记录,sql,gaps-and-islands,Sql,Gaps And Islands,我有以下一组数据: 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 我需要一份报告,显示给定用户的计数,但在没有记

我有以下一组数据:

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)

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

另见:


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

另见:

试试这个:

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
试试这个:

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

这里是按日期范围分组的常规查询@startDate和@endDate定义范围;您可以为用户设置mincreated和maxcreated,或者设置某个固定范围

CTE monthlyRange生成月份表-本月第一个月,下个月第一个月。搜索随后由created与monthlyRanges连接。注意,用户在join中被过滤,因为这是左join,而在where子句中过滤将有效地将其转换为内部join

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

这里是按日期范围分组的常规查询@startDate和@endDate定义范围;您可以为用户设置mincreated和maxcreated,或者设置某个固定范围

CTE monthlyRange生成月份表-本月第一个月,下个月第一个月。搜索随后由created与monthlyRanges连接。注意,用户在join中被过滤,因为这是左join,而在where子句中过滤将有效地将其转换为内部join

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。这非常有效!还感谢您向我介绍SQL fiddle。