处理跨时期的日期范围

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 表达式有两个分支:

    如果DateFromDateTo 列中的任何一个具有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 - 这是一种享受。感谢您也接受我的问题。 很高兴为您提供帮助 :-)

以上是关于处理跨时期的日期范围的主要内容,如果未能解决你的问题,请参考以下文章

请教批处理大虾,如何将一堆不同时期拍摄的照片按修改日期自动创建文件夹进行归档?

跨多个日期范围计算开始日期

请问js如何控制输入日期范围在一个月之内?

根据跨日期范围对订单进行分组

跨多个 Web 应用程序的服务器范围功能

Windows 批处理文件 - 循环遍历日期范围数组,然后拆分每个项目