处理跨时期的日期范围
Posted
技术标签:
【中文标题】处理跨时期的日期范围【英文标题】:Dealing with Date Ranges Crossing Periods 【发布时间】:2019-06-17 06:44:37 【问题描述】:我有一个表格,其中包含跨 DateFrom 和 DateTo 字段以及 TotalValue 字段指定的日期范围。
取决于指定的日期范围,即:
DECLARE @ReportStartDate datetime = '31 May 2019'
DECLARE @ReportEndDate datetime = '2 Jun 2019'
它将获取 NULL 值,以及 2019-05-31-2019-06-07 行,但 TotalValue 将是 (48 / 7) * 2,因为它只有 2 天的范围。
预期结果。
如果指定以下:
DECLARE @ReportStartDate datetime = '04 Jun 2019'
DECLARE @ReportEndDate datetime = '14 Jun 2019'
它将获取 NULL 值以及 2019-05-31-2019-06-05 行,但 TotalValue 将是 (48 / 7) * 3,因为它只有 3 天的范围。
预期结果
有人知道如何解决这个问题吗?到目前为止,我有以下查询可以解决用例 1,但我不确定如何处理用例 2
select
*,
CASE WHEN DateFrom is null Then TotalValue Else (TotalValue/7) * DateDiff(dd,DateFrom,@ReportEndDate) END as CalculatedValue
from
#TestData
where DateFrom is null
or DateFrom >=@ReportStartDate
样本数据
CREATE TABLE #TestData
(
DateFrom date NULL,
DateTo date NULL,
TotalValue money
)
INSERT INTO #TestData
(
DateFrom,
DateTo,
TotalValue
)
SELECT
NULL,
NULL,
250
UNION ALL
SELECT
'2019-05-31',
'2019-06-07',
48
UNION ALL
SELECT
'2019-05-24',
'2019-05-31',
336
UNION ALL
SELECT
NULL,
NULL,
134
UNION ALL
SELECT
'2019-04-19',
'2019-04-26',
336
select * from #TestData
drop table #TestData
【问题讨论】:
不太清楚你在这里问什么。你有什么问题?另外,能否请您显示您遇到问题的查询和预期结果。 您在示例数据方面做得很好,但在所需的输出方面做得还不够。请edit您的问题包括您当前的尝试和您想要的输出作为格式化文本数据集。 抱歉,已添加预期结果。 请阅读"Why not upload images of code on SO when asking a question?"接受的答案。很多重点也与所需的输出有关。 如果你不想 null 使用“where blah is not null” 【参考方案1】:使用case
表达式、datediff
和几个iif
来获得CalculatedValue
。
case 表达式有两个分支:
如果DateFrom
或DateTo
列中的任何一个具有null
而不是value
,则只需返回TotalValue
。
这就是有趣的地方:如果日期范围重叠,计算它们重叠的天数,然后将TotalValue
除以 7 并乘以天数。
我在代码中添加了一些cmets,希望够清楚:
DECLARE @ReportStartDate date = '2019-05-31', @ReportEndDate date = '2019-06-02'
SELECT DateFrom,
DateTo,
TotalValue,
CASE
-- dates are null
WHEN DateFrom IS NULL OR DateTo IS NULL THEN TotalValue
-- devide by 7 and multiply be the number of days within range
ELSE TotalValue / 7 * DATEDIFF(DAY,
-- latest of start dates
IIF(DateFrom > @ReportStartDate, DateFrom, @ReportStartDate),
-- earliest of end dates
IIF(DateTo < @ReportEndDate, DateTo, @ReportEndDate)
)
END As CalculatedValue
FROM #TestData
-- Get only date ranges that overlap or the date columns are null
WHERE (DateFrom IS NULL OR DateFrom < @ReportEndDate)
AND (DateTo IS NULL OR DateTo > @ReportStartDate)
【讨论】:
非常感谢@Zohar Peled。但是,是否可以删除您的第 2 点,因为这些结果不应显示在查询中,因为它们无论如何都不在日期范围内 没问题,但是您必须在 where 子句中添加一个条件来消除这些行。我已经编辑了我的答案以反映这一点。 非常感谢@Zohar Peled - 这是一种享受。感谢您也接受我的问题。 很高兴为您提供帮助 :-)以上是关于处理跨时期的日期范围的主要内容,如果未能解决你的问题,请参考以下文章