TSQL-返回开始日期和结束日期之间每个月的记录,即使该月没有可用数据

TSQL-返回开始日期和结束日期之间每个月的记录,即使该月没有可用数据,sql,sql-server,tsql,Sql,Sql Server,Tsql,我当前的SELECT查询结果如下 SELECT Category, MonthYear, Percentage FROM #Result 起始日期为2018-12-01,结束日期为2019-05-01 但我希望我的结果是在@StartDate和@EndDate之间的所有月份,如果没有该类别的数据,则百分比值为零 Category | MonthYear | Percentage ----------+------------+------------ Category1 | 20

我当前的SELECT查询结果如下

SELECT Category, MonthYear, Percentage 
FROM #Result
起始日期为2018-12-01,结束日期为2019-05-01

但我希望我的结果是在@StartDate和@EndDate之间的所有月份,如果没有该类别的数据,则百分比值为零

Category  | MonthYear  | Percentage
----------+------------+------------    
Category1 | 2018-12-01 | 80 
Category1 | 2019-01-01 | 70
Category1 | 2019-02-01 | 75
Category1 | 2019-03-01 | 60
Category1 | 2019-04-01 | 45
Category1 | 2019-05-01 | 29
Category2 | 2018-12-01 | 0
Category2 | 2019-01-01 | 0
Category2 | 2019-02-01 | 0
Category2 | 2019-03-01 | 78
Category2 | 2019-04-01 | 95
Category2 | 2019-05-01 | 98

您可以使用递归CTE生成日期。然后使用交叉连接和左连接来引入数据。因此:

with dates as (
      select min(monthyear) as yyyymm, max(monthyear) as max_yyyymm
      from t
      union all
      select dateadd(month, 1, yyyymm), max_yyyymm
      from dates
      where yyyymm < max_yyyymm
    )
select c.category, d.yyyymm, coalesce(t.percentage, 0) as percentage
from (select distinct category from t) c cross join
     dates d left join
     t
     on t.category = c.category and t.monthyear = d.yyyymm
order by c.category, d.yyyymm;

显示填充结果的查询。。。这是最有可能需要改变的地方。他可能对此感兴趣@AdnanSharif为什么?COALESCE是ANSI标准,而ISNULL是专有的,并且在另一种Microsoft语言中令人困惑地共享一个名称。Perfect@gordon linoff,这就是我要找的。非常感谢。谁更容易理解?似乎很主观。更合适?为什么?你能给出一个具体的原因,为什么ISNULL比我更喜欢它吗?@AdnanSharif。我在答案中写了COALESCE。它比ISNULL更灵活,因为它接受多个参数并且是标准的。当性能是一个问题时,特别是当第一个参数是一个非常复杂的表达式,如子查询或复杂函数时,您希望使用ISNULL。@Adnan我只知道一种情况,而且它是一种糟糕的模式。还有其他一些细微的区别,但在大多数情况下,在标准的两种方案中,它们是可互换的。与ISNULL相比,COALESCE还有其他优势,因此,除了一个非常特殊的边缘情况外,COALESCE将是一个更好的选择。
with dates as (
      select min(monthyear) as yyyymm, max(monthyear) as max_yyyymm
      from t
      union all
      select dateadd(month, 1, yyyymm), max_yyyymm
      from dates
      where yyyymm < max_yyyymm
    )
select c.category, d.yyyymm, coalesce(t.percentage, 0) as percentage
from (select distinct category from t) c cross join
     dates d left join
     t
     on t.category = c.category and t.monthyear = d.yyyymm
order by c.category, d.yyyymm;