我有一个日历查询和下表。我有一个成员的StartDate和结束日期。同样在我的日历表上,我根据startDate捕获了一个“Weekof”。我希望捕获一个成员是否在该周期间的任何时间处于活动状态。查看预期结果。
SELECT DISTINCT
--CA.CALENDAR_DATE,
TO_CHAR(CALENDAR_DATE,'MM/DD/YYYY') AS CALENDAR_DATE
TO_CHAR(NEXT_DAY(CALENDAR_DATE, 'Monday') - 7, 'MM/DD/YY-') ||
TO_CHAR(NEXT_DAY(CALENDAR_DATE, 'Monday') - 1, 'MM/DD/YY') AS WEEK_OF_YEAR,
ROW_NUMBER () OVER ( ORDER BY CALENDAR_DATE) AS MasterCalendar_RNK
FROM CALENDAR CA
WHERE 1=1
--AND CA.CALENDAR_DATE BETWEEN ADD_MONTHS(TRUNC(SYSDATE), -12) AND TRUNC(SYSDATE)
--AND CA.CALENDAR_DATE BETWEEN TRUNC(SYSDATE) -5 AND TRUNC(SYSDATE)
ORDER BY TO_DATE(CALENDAR_DATE,'MM/DD/YYYY') DESC
表
Member StartDate EndDate
A 1/31/17
B 2/1/17 2/15/17
预期产出:
Member StartDate EndDate Week_Of_Year Active
A 1/31/17 1/30/17-2/5/17 1
A 1/31/17 2/6/17-2/12/17 1
A 1/31/17 2/13/17-2/19/17 1
B 2/1/17 2/15/17 1/30/17/2/5/17 1
B 2/1/17 2/15/17 2/6/17-2/12/17 1
B 2/1/17 2/15/17 2/13/17-2/19/17 1
当前查询:
WITH MASTER_CALENDAR AS (
SELECT TRUNC(SYSDATE) + 1 - LEVEL , A.CALENDAR_DATE
FROM (SELECT C.CALENDAR_DATE FROM MST.CALENDAR C WHERE 1=1 AND C.CALENDAR_DATE > SYSDATE-30 AND C.CALENDAR_DATE < SYSDATE) A
WHERE 1=1
CONNECT BY LEVEL <= 1 --NEED TO UPDATE?
ORDER BY A.CALENDAR_DATE DESC
),
ActiveMembers AS (
SELECT H.CLT_CLT_PGMID, H.START_DT
,CASE WHEN TRUNC(H.END_DT) = '1-JAN-3000'
THEN SYSDATE
ELSE TO_DATE(H.END_DT)
END AS END_DT
FROM H
WHERE 1=1
AND H.CLT_CLT_PGMID IN ('1','2','3')
)
SELECT CLT_CLT_PGMID, STARTDATE, ENDDATE, WEEK_OF_YEAR, ACTIVE -- but not week_start
FROM (
SELECT DISTINCT A.CLT_CLT_PGMID,
TO_CHAR(A.START_DT, 'MM/DD/YY') AS STARTDATE,
TO_CHAR(A.END_DT, 'MM/DD/YY') AS ENDDATE,
NEXT_DAY(CAL.CALENDAR_DATE, 'Monday') - 7 AS WEEK_START, -- for ordering later
TO_CHAR(NEXT_DAY(CAL.CALENDAR_DATE, 'Monday') - 7, 'MM/DD/YY-') ||
TO_CHAR(NEXT_DAY(CAL.CALENDAR_DATE, 'Monday') - 1, 'MM/DD/YY') AS WEEK_OF_YEAR,
1 AS ACTIVE
FROM ActiveMembers A
INNER JOIN MASTER_CALENDAR CAL ON CAL.CALENDAR_DATE BETWEEN A.START_DT AND A.END_DT
--BETWEEN TO_CHAR(A.START_DT,'MM/DD/YYYY') AND COALESCE(A.END_DT,(SYSDATE))
)
WHERE 1=1
ORDER BY
CLT_CLT_PGMID , STARTDATE, ENDDATE, WEEK_START
;
答案 0 :(得分:1)
我以与Alex相似的方式做到这一点,但略有不同。看到你的周从星期一开始,我使用TRUNC(dt, 'iw')
来获得指定日期的ISO开始(恰好定义为星期一)。然后我会在加入你的桌子之前得到那些不同的值,如下所示:
with calendar as (select trunc(sysdate) - level + 1 calendar_date
from dual
connect by level <= 50),
your_table as (select 'A' member, date '2017-01-31' startdate, NULL enddate from dual union all
select 'B' member, date '2017-02-01' startdate, date '2017-02-15' enddate from dual)
select yt.member,
yt.startdate,
yt.enddate,
to_char(c.week_start, 'mm/dd/yyyy')
|| ' - ' || to_char(c.week_start + 6, 'mm/dd/yyyy') week_of_year,
1 as active
from your_table yt
inner join (select distinct trunc(cl.calendar_date, 'iw') week_start
from calendar cl) c on c.week_start <= nvl(yt.enddate, SYSDATE) AND c.week_start + 6 >= yt.startdate
order by yt.member,
c.week_start;
MEMBER STARTDATE ENDDATE WEEK_OF_YEAR ACTIVE
------ ---------- ---------- ----------------------- ----------
A 01/31/2017 01/30/2017 - 02/05/2017 1
A 01/31/2017 02/06/2017 - 02/12/2017 1
A 01/31/2017 02/13/2017 - 02/19/2017 1
A 01/31/2017 02/20/2017 - 02/26/2017 1
B 02/01/2017 02/15/2017 01/30/2017 - 02/05/2017 1
B 02/01/2017 02/15/2017 02/06/2017 - 02/12/2017 1
B 02/01/2017 02/15/2017 02/13/2017 - 02/19/2017 1
和Alex一样,我假设您的null enddate一直运行到今天(sysdate)。但是,查看成员B的结果,看起来你正在寻找一个重叠的范围(因为1月30日不是2月1日到15日之间),所以我相应地修改了我的连接条款。这会导致成员A的额外行,所以您可能希望在sysdate的上一个星期日之前运行null enddates?不确定。如果您需要,我确定您可以自行修改。