2017-02-23 8 views
1

私は以下のカレンダークエリとテーブルを持っています。私は会員のための開始日と終了日を持っています。また、私のカレンダーテーブルでは、startDateに基づいて "Weekof"を取得しました。その週の間、いつでもメンバーがアクティブであるかどうかを確認したいと思います。期待される結果を参照してください。日付範囲に基づいて複数の行を作成する

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 

現在のクエリ:出力期待

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 

カレンダーのクエリは、現在の文字列を生成しているため

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 
        ; 

答えて

1

、戻って単純だろうカレンダーテーブルに、joi nは、あなたのメンバー/日付テーブルへの、および週の範囲の文字列を再生成:

with calendar(calendar_date) as (
    select trunc(sysdate) + 1 - level from dual connect by level <= 42 
), 
mytable (member, startdate, enddate) as (
    select cast('A' as varchar2(6)), date '2017-01-31', cast (null as date) from dual 
    union all select cast('B' as varchar2(6)), date '2017-02-01', date '2017-02-15' from dual 
) 
select member, startdate, enddate, week_of_year, active -- but not week_start 
from (
    select distinct m.member, 
     to_char(m.startdate, 'MM/DD/YY') as startdate, 
     to_char(m.enddate, 'MM/DD/YY') as enddate, 
     next_day(c.calendar_date, 'Monday') - 7 as week_start, -- for ordering later 
     to_char(next_day(c.calendar_date, 'Monday') - 7, 'MM/DD/YY-') || 
     to_char(next_day(c.calendar_date, 'Monday') - 1, 'MM/DD/YY') as week_of_year, 
     1 as active 
    from mytable m 
    join calendar c 
    on c.calendar_date between m.startdate and coalesce(m.enddate, trunc(sysdate)) 
) 
order by member, startdate, enddate, week_start; 

のCTEでは、会員データ(ちょうど今の最後の数週間の日付で)カレンダーテーブルを表現します

MEMBER STARTDAT ENDDATE WEEK_OF_YEAR   ACTIVE 
------ -------- -------- ----------------- ---------- 
A  01/31/17   01/30/17-02/05/17   1 
A  01/31/17   02/06/17-02/12/17   1 
A  01/31/17   02/13/17-02/19/17   1 
A  01/31/17   02/20/17-02/26/17   1 
B  02/01/17 02/15/17 01/30/17-02/05/17   1 
B  02/01/17 02/15/17 02/06/17-02/12/17   1 
B  02/01/17 02/15/17 02/13/17-02/19/17   1 

取得あなたはノー終了日を持つメンバーの上限を指定していないので、私はcoalesce()を経て、現在使用されてきました。

内側のクエリは、注文のためにのみ必要です。週の範囲の文字列は使用できず、週の開始を自分自身で見たくないためです。選択していないフィールドでは別名と順序を使用することはできません。

+0

私はカレンダーの最後の30日しか必要ないので、結果のためにサブクエリを追加しました。私は接続することに慣れていませんが、接続レベルを<= 42から<= 1に変更しました。これが何をするのか分かりません。あなたは説明することができ、クエリは私の例では機能しますが、その方法を理解できません。 – John

+0

あなたの答えに基づいて私の質問の下に私の現在の質問が表示されます。 – John

+0

@ John - 42では、connect-subqueryが返す行の数を制限しています。その数字には特に関係はありません。あなたのサンプルデータに少なくとも十分な日付を生成するものを選んだだけです。そのサブクエリを単独で実行すると、一連の個別の日付が生成されます。 42を30に変更すると、最後の42日ではなく最後の30日が生成されます(1に変更すると1つの日付しか表示されません)。しかし、あなたのカレンダーテーブルから日付を取得している場合、あなたは接続する必要は全くありません。 (私はCTEがあなたの実際のデータを表現すると述べた。) –

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 

を、私はあなたのヌル終了日が今日(SYSDATE)まで走ると仮定しました。しかし、メンバーBの結果を見てみると、1月30日が2月1日から15日までではないので、重複範囲を探しているように見えるので、私はそれに応じて結合節を修正しました。この結果、メンバーAの余分な行が生成されます。したがって、sysdateの前の日曜日までnullの終了日を実行したいことがありますか?わからない。あなたが必要なら、自分でそれを修正できると確信しています。

関連する問題