理解TSQL合并函数

理解TSQL合并函数,tsql,coalesce,Tsql,Coalesce,我正在尝试选择所有12个月/年。我认为下面的TSQL代码可以做到这一点。然而,这并不包括我想要的所有月份。这是什么原因?这是修改后的代码: DECLARE @END_YEAR VARCHAR(10) DECLARE @END_MONTH VARCHAR(10) SET @END_YEAR = '2010' SET @END_MONTH = '10' DECLARE @TheMonthLastDate DATETIME DECLARE @TempDate DATETIME SET @TempD

我正在尝试选择所有12个月/年。我认为下面的TSQL代码可以做到这一点。然而,这并不包括我想要的所有月份。这是什么原因?这是修改后的代码:

DECLARE @END_YEAR VARCHAR(10)
DECLARE @END_MONTH VARCHAR(10)

SET @END_YEAR = '2010'
SET @END_MONTH = '10'

DECLARE @TheMonthLastDate DATETIME
DECLARE @TempDate DATETIME
SET @TempDate = '2010-11-01 00:00:00.000'
SET @TheMonthLastDate = '2010-11-01 00:00:00.000'

;with months
as  
(
select dateadd(month, -1, dateadd(day, datediff(day, 0, @TempDate), 0)) as m
union all
select dateadd(month, -1, m)
from months
where   m > dateadd(month, -12, @TempDate)
)
,yourTable(DateOpened, DateClosed)
as
(select TSK_START_DATE, BTK_CLOSED_DATE
FROM [PROC].ALL_AUDIT
WHERE 
(BTK_CLOSED_DATE < @TheMonthLastDate OR
TSK_START_DATE < @TheMonthLastDate 
)
)
select      yt.DateClosed 'r2', m.m 'r3',
        month(coalesce(yt.DateClosed, m.m)) as 'MonthClosed',
        year(coalesce(yt.DateClosed, m.m)) as 'YearClosed'
from    months m
left join yourTable yt
    on      
    (  datepart(year, yt.DateClosed) = DATEPART(year, m.m)
    and datepart(month, yt.DateClosed) = DATEPART(month, m.m) 
    or    
      datepart(year, yt.DateOpened) = DATEPART(year, m.m)
    and datepart(month, yt.DateOpened) = DATEPART(month, m.m) 
    )
AND year(coalesce(yt.DateClosed, m.m)) = 2010
order by yt.DateClosed
但如果我使用WHERE: BTK_关闭日期<@TheMonthLastDate或 TSK_开始日期<@TheMonthLastDate

然后我明白了:

r2  r3  MonthClosed YearClosed
NULL    2010-10-01 00:00:00.000 10  2010
NULL    2010-09-01 00:00:00.000 9   2010
NULL    2010-09-01 00:00:00.000 9   2010
NULL    2010-08-01 00:00:00.000 8   2010
NULL    2010-08-01 00:00:00.000 8   2010
...
所以请注意,在第一个结果中,我看到2010年6月的空值,这就是我想要的。
我认为这个问题与我的数据包含2009-2011年的数据有关,但我只比较了月份,而不是年份。如何添加此附加逻辑?

减少数据的唯一地方是使用已标识的where子句。因此,您无法获得预期的所有月份的原因是TSK_START_DATE列在所有月份中都不小于@TheMonthLastDate

为了证明这一假设,请运行查询的以下部分,我已注释掉where子句的一部分,并删除了“yourTable”cte下的所有内容。结果应显示TSK_Start_Date列中为缺少的月份返回的内容,并帮助您确定在应用<@TheMonthLastDate子句时缺少行的原因

DECLARE @END_YEAR VARCHAR(10)
DECLARE @END_MONTH VARCHAR(10)

SET @END_YEAR = '2010'
SET @END_MONTH = '10'

DECLARE @TheMonthLastDate DATETIME
DECLARE @TempDate DATETIME
SET @TempDate = '2010-11-01 00:00:00.000'
SET @TheMonthLastDate = '2010-11-01 00:00:00.000'

;with months
as  
(
select dateadd(month, -1, dateadd(day, datediff(day, 0, @TempDate), 0)) as m
union all
select dateadd(month, -1, m)
from months
where   m > dateadd(month, -12, @TempDate)
)

,yourTable(DateOpened, DateClosed)
as
(select TSK_START_DATE, BTK_CLOSED_DATE
FROM [PROC].ALL_AUDIT
WHERE 
(BTK_CLOSED_DATE < @TheMonthLastDate OR
--TSK_START_DATE < @TheMonthLastDate 
)
)
select * , @TheMonthLastDate TheMonthLastDate from yourTable

目前没有时间阅读所有代码,但为了回答标题的问题,coalesce本质上是一个ISNULL,包含多个参数,其中返回第一个非null参数。yourTable CTE中的select语句在使用OR或not时是否返回相同的精确数据?Derek,不,它不返回。不使用或返回102条记录。使用或返回134条记录。问题的一部分是我不完全理解CTE是如何工作的。好吧,把CTE看作一个视图,因为它就是这样。唯一的区别是它不存储在数据库中,CTE只用于一个查询。因此,这是一个一次性视图。我要说的是,添加OR导致不返回任何记录是没有意义的,但是遵循您的代码非常困难。如果你能以某种方式发布一个精简版,展示出我们可以调查的相同模式,这将更容易提供帮助。谢谢你的评论,德里克。我现在只是转载了更简单的代码。你能看看这个吗?
r2  r3  MonthClosed YearClosed
NULL    2010-10-01 00:00:00.000 10  2010
NULL    2010-09-01 00:00:00.000 9   2010
NULL    2010-09-01 00:00:00.000 9   2010
NULL    2010-08-01 00:00:00.000 8   2010
NULL    2010-08-01 00:00:00.000 8   2010
...
DECLARE @END_YEAR VARCHAR(10)
DECLARE @END_MONTH VARCHAR(10)

SET @END_YEAR = '2010'
SET @END_MONTH = '10'

DECLARE @TheMonthLastDate DATETIME
DECLARE @TempDate DATETIME
SET @TempDate = '2010-11-01 00:00:00.000'
SET @TheMonthLastDate = '2010-11-01 00:00:00.000'

;with months
as  
(
select dateadd(month, -1, dateadd(day, datediff(day, 0, @TempDate), 0)) as m
union all
select dateadd(month, -1, m)
from months
where   m > dateadd(month, -12, @TempDate)
)

,yourTable(DateOpened, DateClosed)
as
(select TSK_START_DATE, BTK_CLOSED_DATE
FROM [PROC].ALL_AUDIT
WHERE 
(BTK_CLOSED_DATE < @TheMonthLastDate OR
--TSK_START_DATE < @TheMonthLastDate 
)
)
select * , @TheMonthLastDate TheMonthLastDate from yourTable