SQL Server:分组依据以检索具有0的行

时间:2018-11-14 11:56:21

标签: sql sql-server group-by

我有一个查询,它检索按月分组的计数列表,如下所示

 SELECT 
     CASE 
        WHEN MONTH(StartDate) = 1 THEN 'January'
        WHEN MONTH(StartDate) = 2 then 'February'                         
        WHEN MONTH(StartDate) = 3 then 'March'
        WHEN MONTH(StartDate) = 4 then 'April'
        WHEN MONTH(StartDate) = 5 then 'May'
        WHEN MONTH(StartDate) = 6 then 'June'
        WHEN MONTH(StartDate) = 7 then 'July'
        WHEN MONTH(StartDate) = 8 then 'August'
        WHEN MONTH(StartDate) = 9 then 'September'
        WHEN MONTH(StartDate) = 10 then 'October'
        WHEN MONTH(StartDate) = 11 then 'November'
        WHEN MONTH(StartDate) = 12 then 'December' 
        ELSE '' 
     END AS [month],
     COUNT(*) AS Count
 FROM
     Users
 WHERE
     YEAR(StartDate) = '2018'
 GROUP BY
     MONTH(StartDate)
 ORDER BY 
     MONTH(StartDate)

结果看起来像这样:

Month    | Count
---------+-------
January  |   1
February |   2
April    |   7
May      |   3

如您所见,列表中缺少想要检索ID的月份。 预期结果:

Month    | Count
---------+-------
January  |   1
February |   2
March    |   0
April    |   7
May      |   3
June     |   0

等等...

如何获得零计数的月份?

3 个答案:

答案 0 :(得分:2)

您可以尝试制作日历表,然后outer join对其进行操作。

将条件YEAR(StartDate) = '2018'ON移动到WHERE,因为您需要使用OUTER JOIN

order by startnum列。

;WITH CTE AS (
   SELECT 1 startnum,12 endnum
   UNION ALL
   SELECT startnum +1 ,endnum
   FROM CTE 
   where startnum +1  <= endnum
)
SELECT 
     t1.dt as [month],
     Count(Users.StartDate) as Count
 FROM (
    SELECT DATENAME(month, DATEADD(month, startnum - 1, CAST('1900-01-01' AS date))) dt,startnum
    FROM CTE 
 ) t1 LEFT JOIN  Users on t1.startnum = MONTH(StartDate) AND YEAR(StartDate) = '2018'
 GROUP by t1.dt,t1.startnum
 ORDER BY t1.startnum

sqlfiddle

答案 1 :(得分:0)

您可以使用<a>构造并执行<span>

<%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<%@ taglib uri="http://www.springframework.org/tags" prefix="spring"%>
<%@ taglib uri="http://www.springframework.org/tags/form" prefix="form"%>
<%@ taglib prefix = "fmt" uri = "http://java.sun.com/jsp/jstl/fmt" %>
<%@ page session="false"%> 

<form:form action="" commandName="someDetail">
<form:input path="name" class="form-control" />
<form:input path="address" class="form-control" />

答案 2 :(得分:0)

生成月开始日期列表,并在查询中使用这些日期:

with dates as (
      select cast('2018-01-01' as date) as dte, 1 as num
      union all
      select dateadd(month, 1, dte), num + 1
      from dates
      where num < 12
     )
select year(d.dte), datename(month, d.dte), count(u.startdate)
from dates d left join
     users u
     on month(u.startdate) >= month(d.dte)
where u.startdate >= '2018-01-01' and
      u.startdate < '2019-01-01' 
group by d.dte
order by d.dte;

这将使用递归CTE生成月份。注意其他一些变化:

  • 查询中明确包含年份,以确保即使扩大日期范围,查询也能继续执行您期望的操作。
  • 日期范围是使用范围而不是year()定义的。这是最佳做法,因此查询可以利用索引。
  • 因为日期函数可以提取月份名称,所以不需要case表达式。