Sql 在日期查询中填写缺少的月份

Sql 在日期查询中填写缺少的月份,sql,sql-server,Sql,Sql Server,我在微软SQL Server 2017上工作。 我正试图在数据查询中填充缺少的月份 查询是: SELECT Concat(Datename(mm, temp1.InvoiceDate), '-', Datepart(yy, Getdate())) AS 'Date' , temp1.[Partner], Count(temp1.issues) AS 'Total' FROM temp1 GROUP BY temp1.InvoiceDate, temp1.[partner] ORDER

我在微软SQL Server 2017上工作。 我正试图在数据查询中填充缺少的月份

查询是:

SELECT Concat(Datename(mm, temp1.InvoiceDate), '-', Datepart(yy, Getdate())) AS 'Date' , temp1.[Partner], Count(temp1.issues) AS 'Total' 
FROM   temp1 
GROUP  BY temp1.InvoiceDate, temp1.[partner] 
ORDER  BY Datepart(mm, temp1.InvoiceDate), temp1.[partner];
不要介意getdate,因为我将始终处理实际的年份数据

它向我展示了这个结果:

Date        Partner             Total
April-2020  Enterprise1, S.A.   1
May-2020    Enterprise2, S.A.   1
July-2020   Enterprise2, S.A.   2
这是正确的,但我也需要有丢失的月份,直到实际月份,即getdate实际月份,其中没有数据

比如:

Date           Partner           Total
January-2020   N/A                0
February-2020  N/A                0
March-2020     N/A                0
April-2020     Enterprise1, S.A.  1
May-2020       Enterprise2, S.A.  1
June-2020      N/A                0
July-2020      Enterprise2, S.A.  2
August-2020    N/A                0
September-2020 N/A                0
另外,我不想看到实际的几个月

PS:我不能在我的开发环境中使用t-SQL代码声明等


提前感谢。

我将使用递归CTE生成一年的日期:

with dates as (
      select datefromparts(year(getdate()), 1, 1) as yyyymm
      union all
      select dateadd(month, 1, yyyymm)
      from dates
      where yyyymm < getdate()
     )
select d.yyyymm, t1.partner, count(t1.issues)
from dates d left join
     temp1 t1 
     ON t1.InvoiceDate >= d.yyyymm AND
        t1.InvoiceDate < dateadd(month, 1, d.yyyymm)
group by d.yyyymm, t1.partner
order by d.yyyymm, t1.partner;

我将使用递归CTE生成该年的日期:

with dates as (
      select datefromparts(year(getdate()), 1, 1) as yyyymm
      union all
      select dateadd(month, 1, yyyymm)
      from dates
      where yyyymm < getdate()
     )
select d.yyyymm, t1.partner, count(t1.issues)
from dates d left join
     temp1 t1 
     ON t1.InvoiceDate >= d.yyyymm AND
        t1.InvoiceDate < dateadd(month, 1, d.yyyymm)
group by d.yyyymm, t1.partner
order by d.yyyymm, t1.partner;

递归CTE的一种替代方法是使用数字表(有时也称为“tally”表)进行查询。只有12个月,因此可以在代码中枚举它,然后不需要递归。此外,为了输入年份,我添加了一个变量,该变量采用逗号分隔的列表。本例中的示例为2年,即2020年和2021年

像这样的

declare
  @report_yrs  varchar(100)='2020,2021';

with ent_cte(InvoiceDate, [Partner], [issues]) as
    (select '2020-03-01', 'Enterprise1, S.A.', 'x'
     union all
     select '2020-04-01', 'Enterprise1, S.A.', 'x'
     union all
     select '2020-05-01', 'Enterprise1, S.A.', 'x'
     union all
     select '2020-12-01', 'Enterprise1, S.A.', 'x')
SELECT Concat(Datename(mm, dfp.dfp), '-', Datepart(yy, dfp.dfp)) AS [Date],
       isnull(t.[Partner], 'N/A') [Partner], Count(t.issues) AS [Total] 
FROM string_split(@report_yrs, ',') sp
     cross join
     (values (1),(2),(3),(4),(5),(6),(7),(8),(9),(10),(11),(12)) v(mo)
     cross apply
     (select datefromparts(cast(sp.[value] as int), v.mo, 1) dfp) dfp
     left join 
     ent_cte t on dfp.dfp=t.InvoiceDate
GROUP  BY dfp.dfp, t.[partner] 
ORDER  BY dfp.dfp, t.[partner];
输出

Date            Partner Total
January-2020    N/A     0
February-2020   N/A     0
March-2020      Enterprise1, S.A.   1
April-2020      Enterprise1, S.A.   1
May-2020        Enterprise1, S.A.   1
June-2020       N/A     0
July-2020       N/A     0
August-2020     N/A     0
September-2020  N/A     0
October-2020    N/A     0
November-2020   N/A     0
December-2020   Enterprise1, S.A.   1
January-2021    N/A     0
February-2021   N/A     0
March-2021      N/A     0
April-2021      N/A     0
May-2021        N/A     0
June-2021       N/A     0
July-2021       N/A     0
August-2021     N/A     0
September-2021  N/A     0
October-2021    N/A     0
November-2021   N/A     0
December-2021   N/A     0

递归CTE的一种替代方法是使用数字表(有时也称为“tally”表)进行查询。只有12个月,因此可以在代码中枚举它,然后不需要递归。此外,为了输入年份,我添加了一个变量,该变量采用逗号分隔的列表。本例中的示例为2年,即2020年和2021年

像这样的

declare
  @report_yrs  varchar(100)='2020,2021';

with ent_cte(InvoiceDate, [Partner], [issues]) as
    (select '2020-03-01', 'Enterprise1, S.A.', 'x'
     union all
     select '2020-04-01', 'Enterprise1, S.A.', 'x'
     union all
     select '2020-05-01', 'Enterprise1, S.A.', 'x'
     union all
     select '2020-12-01', 'Enterprise1, S.A.', 'x')
SELECT Concat(Datename(mm, dfp.dfp), '-', Datepart(yy, dfp.dfp)) AS [Date],
       isnull(t.[Partner], 'N/A') [Partner], Count(t.issues) AS [Total] 
FROM string_split(@report_yrs, ',') sp
     cross join
     (values (1),(2),(3),(4),(5),(6),(7),(8),(9),(10),(11),(12)) v(mo)
     cross apply
     (select datefromparts(cast(sp.[value] as int), v.mo, 1) dfp) dfp
     left join 
     ent_cte t on dfp.dfp=t.InvoiceDate
GROUP  BY dfp.dfp, t.[partner] 
ORDER  BY dfp.dfp, t.[partner];
输出

Date            Partner Total
January-2020    N/A     0
February-2020   N/A     0
March-2020      Enterprise1, S.A.   1
April-2020      Enterprise1, S.A.   1
May-2020        Enterprise1, S.A.   1
June-2020       N/A     0
July-2020       N/A     0
August-2020     N/A     0
September-2020  N/A     0
October-2020    N/A     0
November-2020   N/A     0
December-2020   Enterprise1, S.A.   1
January-2021    N/A     0
February-2021   N/A     0
March-2021      N/A     0
April-2021      N/A     0
May-2021        N/A     0
June-2021       N/A     0
July-2021       N/A     0
August-2021     N/A     0
September-2021  N/A     0
October-2021    N/A     0
November-2021   N/A     0
December-2021   N/A     0

您将在数据库中只找到您放入其中的数据。 在这种情况下,建议添加一些datetime表,例如每天一行的日历表和一些其他表,如月、日、周

当在数据库中创建时,查询将变得简单而高效,而不是使用表值函数的递归查询,所有这些都将耗费大量的时间和过程

对于您的情况,这可以是:

CREATE TABLE T_MONTH 
(
MONTH_NUM   TINYINT PRIMARY KEY,
MONTH_NAME  VARCHAR(16) NOT NULL UNIQUE
);
DECLARE @I INT = 1, @D DATE = '2000-01-01'
WHILE @I <= 12
BEGIN
   INSERT INTO T_MONTH
   SELECT @I, DATENAME(month, DATEADD(month, @I - 1, @D));
   SET @I = @I + 1;
END

您将在数据库中只找到您放入其中的数据。 在这种情况下,建议添加一些datetime表,例如每天一行的日历表和一些其他表,如月、日、周

当在数据库中创建时,查询将变得简单而高效,而不是使用表值函数的递归查询,所有这些都将耗费大量的时间和过程

对于您的情况,这可以是:

CREATE TABLE T_MONTH 
(
MONTH_NUM   TINYINT PRIMARY KEY,
MONTH_NAME  VARCHAR(16) NOT NULL UNIQUE
);
DECLARE @I INT = 1, @D DATE = '2000-01-01'
WHILE @I <= 12
BEGIN
   INSERT INTO T_MONTH
   SELECT @I, DATENAME(month, DATEADD(month, @I - 1, @D));
   SET @I = @I + 1;
END

我尝试了您的代码,但SQL抛出了一个错误:DATEFROMPARTS不是可识别的内置函数名。我怎样才能让它工作?我在14.0.2027.2版本,所以它应该是兼容的。。。谢谢。@operamaxi。它在所有受支持的SQL Server版本中都可用:。我发现了错误,第一个括号从未闭合。你能编辑一下你的答案吗?我打赌这一改变会使它起作用。谢谢。找到了,它必须添加在getdate之后:选择datefrompartsyeargetdate,1,1作为yyyymm。谢谢我试过了,但它只显示了10月份之前的所有月份。它能显示到12月或9月的实际月份吗?谢谢。我尝试了你的代码,但是SQL抛出了一个错误:DATEFROMPARTS不是可识别的内置函数名。我怎样才能让它工作?我在14.0.2027.2版本,所以它应该是兼容的。。。谢谢。@operamaxi。它在所有受支持的SQL Server版本中都可用:。我发现了错误,第一个括号从未闭合。你能编辑一下你的答案吗?我打赌这一改变会使它起作用。谢谢。找到了,它必须添加在getdate之后:选择datefrompartsyeargetdate,1,1作为yyyymm。谢谢我试过了,但它只显示了10月份之前的所有月份。它能显示到12月或9月的实际月份吗?谢谢