【问题标题】:Counting the Number of Days an Entry is Active within a particular month using a Date Range in Proc SQL使用 Proc SQL 中的日期范围计算条目在特定月份内处于活动状态的天数
【发布时间】:2021-06-28 20:48:33
【问题描述】:

我在一段时间内获得了一些数据,但在弄清楚一些细节时遇到了困难。

例如,我有大量具有活动STARTSTOP 日期的数据行。如果出现以下三种情况之一,我已经执行了笛卡尔积将我的特定数据行加入到该特定月份:

  1. 项目活动开始日期出现在该特定月份的第一天之前,而该项目的活动停止日期出现在该月的第一天之后。 (ITEM_START<= CalendarMonthStart and ITEM_STOP>= CalendarMonthStart)
  2. 项目活动开始日期出现在该特定月份的第一天之后,而该项目的活动停止日期出现在该特定月份的最后一天之前(活动在单个月份内)。(ITEM_START>= CalendarMonthStart and ITEM_STOP>= CalendarMonthEnd)
  3. 项目活动开始日期在该特定月份的最后一天之前,在该特定月份的最后一天之后停止。(ITEM_START<= CalendarMonthEnd and ITEM_STOP>= CalendarMonthEnd)

我的 proc sql 查询示例:

proc sql;
create table  earned_activity as

select
      a.ITEM_START,
      a.ITEM_STOP,
      b.MonthName,
      b.CalendarMonthStart,
      b.CalendarMonthEnd
/* Need to do something here */
from item_activity as a
left join calendar_table as b on 
          (ITEM_START<= CalendarMonthStart and ITEM_STOP>= CalendarMonthStart) or
          (ITEM_START>= CalendarMonthStart and ITEM_STOP>= CalendarMonthEnd) or
          (ITEM_START<= CalendarMonthEnd and ITEM_STOP>= CalendarMonthEnd)

;
quit;

将这三个案例加入我的数据后,我有一些示例数据,如下所示:

ITEM_START ITEM_STOP MonthName CalendarMonthStart CalendarMonthEnd num_days_active
2021-01-06 2021-03-06 Jan 2021-01-01 2021-01-31 25
2021-01-06 2021-03-06 Feb 2021-02-01 2021-02-28 28
2021-01-06 2021-03-06 Mar 2021-03-01 2021-03-31 6

如您所见,对于笛卡尔积,我有一个项目在三个不同的日历月内都有活动。我想找到一种方法来获取该项目在每个月中存在的天数。我的第一个想法是在每个月的每一天执行笛卡尔积,并以某种方式计算那一天是否活跃,但我相信这可能会很快变得庞大而繁琐。是否有执行此类操作的好方法?

谢谢。

【问题讨论】:

    标签: sql sql-server date cartesian-product proc-sql


    【解决方案1】:

    我认为,您只需要开始的最大值和结束的最小值。

    SELECT
        DATEDIFF(day,
            CASE WHEN CalendarMonthStart > a.ITEM_START THEN CalendarMonthStart ELSE a.ITEM_START END,
            CASE WHEN CalendarMonthEnd   < a.ITEM_STOP  THEN CalendarMonthEnd   ELSE a.ITEM_START END)
    

    此外,您的WHERE 可以更简单:

    inner join calendar_table as b on 
              (ITEM_START <= CalendarMonthEnd and ITEM_STOP => CalendarMonthStart)
    

    【讨论】:

    • 太棒了!我将对此进行测试,看看会发生什么。更好的where 条件建议。谢谢。
    • 我认为这很好用。在您的第二个case when 中,我认为else 子句应该是a.ITEM_STOP_DT。同样在连接的where 子句中,它们应该在条件句中包含等效的情况,因为项目可能在月开始/月结束时停止/开始,我们仍然希望将这一天算作活动日期。
    • 如果是这种情况,那么您需要&gt;= &lt;=。如果您仔细阅读条件,您会发现我们将一个区间的 start 与另一个区间的 end 和 v.v. 进行比较
    • 按照您所写的逻辑,如果项目的开始在(或等于)CalendarMonthStart 之后并且项目的停止在 CalendarMonthEnd 之前(基本上它只有在月),您的逻辑将导致 datediff 获取 ITEM_STRT 和 ITEM_STRT 之间的天数差,从而导致 0 天,但实际上它应该找到从 ITEM_STRT 到 ITEM_END 存在的天数?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-11-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多