0

我有以下查询:

SELECT DISTINCT
    YEAR(DateRegistered) as Years,
    Months.[MonthName], 
    COUNT(UserID)as totalReg 
FROM 
    Months WITH(NOLOCK)
LEFT OUTER JOIN
    UserProfile WITH(NOLOCK)
ON 
    Months.MonthID = MONTH(DateRegistered)
AND
    DateRegistered > DATEADD(MONTH, -12,GETDATE())

GROUP BY YEAR(DateRegistered), Months.[MonthName]
ORDER BY Months.[MonthName]

如您所知,这将始终带回 12 个月的数据。因此它正在工作,尽管这种方法存在错误。

它在没有数据的月份创建 Null 值,现在记录应该存在(查询的全部点)但是 Year 字段带来了 Null,这是我不想要的。

现在我明白问题是因为没有数据,它怎么知道是哪一年?

所以我的问题是 - 有没有办法解决这个问题并替换空值?我怀疑我将不得不彻底改变我的方法论。

**YEAR**    **MONTH**             **TOTAL**
2013    April                   1
2013    August                  1
NULL    December                0
2013    February                8
2013    January                 1
2013    July                    1
NULL    June                    0
2013    March                   4
NULL    May                     0
NULL    November                0
NULL    October                 0
2012    September               3
4

4 回答 4

3

如果您想要 12 个月的数据,则构建一个从 1 到 12 的数字列表,并将它们用作偏移量getdate()

with nums as (
      select 12 as level union all
      select level - 1
      from nums
      where level > 1
    )
 select YEAR(thedate) as Years,
        Months.[MonthName], 
        COUNT(UserID) as totalReg 
 FROM (select DATEADD(MONTH, - nums.level, GETDATE()) as thedate
       from nums
      ) mon12 left outer join
      Months WITH (NOLOCK)
      on month(mon12.thedate) = months.monthid left outer join
      UserProfile WITH (NOLOCK)
      ON Months.MonthID = MONTH(DateRegistered) and
         DateRegistered > DATEADD(MONTH, -12, GETDATE())
GROUP BY YEAR(thedate), Months.[MonthName]
ORDER BY Months.[MonthName];

不过,我发现查询有些奇怪。您正在定义从当前日期开始的跨度。但是,您似乎将月份本身划分为日历边界。我也觉得桌子months很尴尬。你为什么不只使用datename()andmonth()函数?

于 2013-08-30T11:04:48.230 回答
1

试试这个:

;With dates as (
Select  DateName(Month, getdate()) as [Month],
        DatePart(Year, getdate()) as [Year],
        1 as Iteration

Union All

Select  DateName(Month,DATEADD(MONTH, -Iteration, getdate())),
        DatePart(Year,DATEADD(MONTH, -Iteration, getdate())),
        Iteration + 1

from dates
where  Iteration < 12
)
SELECT DISTINCT
        d.Year,
        d.Month as [MonthName], 
        COUNT(up.UserID)as totalReg 
FROM dates d
LEFT OUTER JOIN UserProfile up ON d.Month = DateName(DateRegistered)
                                And d.Year = DatePart(Year, DateRegistered)
GROUP BY d.Year, d.Month
ORDER BY d.Year, d.Month
于 2013-08-30T11:19:14.657 回答
0

这是我的解决方案尝试:

declare @UserProfile table
(
    id bigint not null identity(1,1) primary key clustered
    , name nvarchar(32) not null
    , dateRegistered datetime not null default(getutcdate())
)
insert @UserProfile
select 'person 1', '2011-01-23'
union select 'person 2', '2013-01-01'
union select 'person 3', '2013-05-27'

declare @yearMin int, @yearMax int
select @yearMin = year(MIN(dateRegistered))
, @yearMax= year(MAX(dateRegistered))
from @UserProfile

;with monthCte as
(
    select 1 monthNo, DATENAME(month, '1900-01-01') Name
    union all
    select monthNo + 1, DATENAME(month, dateadd(month,monthNo,'1900-01-01'))
    from monthCte
    where monthNo < 12
)
, yearCte as
(
    select @yearMin yearNo
    union all
    select yearNo + 1
    from yearCte
    where yearNo < @yearMax
)
select y.yearNo, m.Name, COUNT(up.id) UsersRegisteredThisPeriod
from yearCte y
cross join monthCte m
left outer join @UserProfile up
    on year(up.dateRegistered) = y.yearNo
    and month(up.dateRegistered) = m.monthNo
group by y.yearNo, m.monthNo, m.Name
order by y.yearNo, m.monthNo 

SQL小提琴版本:http ://sqlfiddle.com/#!6/d41d8/6640

于 2013-08-30T11:25:21.893 回答
0

您必须先计算派生表(或 CTE)中的计数,然后再加入

未经测试:

SELECT 
    COALESCE(dt.Years, YEAR(DATEADD(MONTH, -Months.MonthID, GETDATE()))),
    Months.[MonthName], 
    COALESCE(dt.totalReg, 0) 
FROM 
    Months WITH(NOLOCK)
LEFT OUTER JOIN
 (
   SELECT 
       YEAR(DateRegistered) AS Years,
       MONTH(DateRegistered) AS Mon,
       COUNT(UserID)AS totalReg
   FROM UserProfile WITH(NOLOCK)
   WHERE DateRegistered > DATEADD(MONTH, -12,GETDATE())
   GROUP BY 
       YEAR(DateRegistered),
       MONTH(DateRegistered)
 ) AS dt
ON Months.MonthID = dt.mon
ORDER BY 1, Months.MonthID

我将订单更改为 Months.MonthID 而不是 MonthName,并添加了年份,因为您的结果中可能包含 2012 年 8 月和 2013 年 8 月。

于 2013-08-30T10:53:19.190 回答