问题描述
我在一段时间内获得了一些数据,但在弄清楚一些细节方面遇到了困难。
例如,我有大量具有活动 START
和 STOP
日期的数据行。如果发生以下三种情况之一,我已执行笛卡尔积以将我的特定数据行连接到该特定月份:
- 项目活动开始日期在该特定月份的第一天之前,该项目的活动停止日期在该月的第一天之后。
(ITEM_START<= CalendarMonthStart and ITEM_STOP>= CalendarMonthStart)
- 项目活动开始日期发生在该特定月份的第一天之后,该项目的活动停止日期发生在该特定月份的最后一天之前(活动在一个月内)。
(ITEM_START>= CalendarMonthStart and ITEM_STOP>= CalendarMonthEnd)
- 项目活动开始日期发生在该特定月份的最后一天之前,并在该特定月份的最后一天之后停止。
(ITEM_START<= CalendarMonthEnd and ITEM_STOP>= CalendarMonthEnd)
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 | 月份名称 | CalendarMonthStart | CalendarMonthEnd | num_days_active |
---|---|---|---|---|---|
2021-01-06 | 2021-03-06 | 一月 | 2021-01-01 | 2021-01-31 | 25 |
2021-01-06 | 2021-03-06 | 二月 | 2021-02-01 | 2021-02-28 | 28 |
2021-01-06 | 2021-03-06 | 三月 | 2021-03-01 | 2021-03-31 | 6 |
如您所见,使用笛卡尔积,我有一个项目在三个不同的日历月内都有活动。我想找到一种方法来获取该项目在每个月中存在的天数。我的第一个想法是在每个月的每一天执行笛卡尔乘积,如果那一天活跃,则以某种方式进行统计,但我相信这可能会很快变得庞大而繁琐。是否有执行此类操作的好方法?
谢谢。
解决方法
我认为你只需要开始和结束的最大值。
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)