1

次のようなテーブルがあります。

Id    Begin_Date    End_date    
1     01-JAN-12     05-JAN-12
1     01-FEB-12     01-MAR-12
1     15-FEB-12     05-MAR-12

特定の Id に対して、一連の日付範囲を提供します。日付がその ID の開始日と終了日の間にある場合、その ID は「オン」であるとしましょう。それ以外の場合は「オフ」

ここでの問題は、これらの最後の 2 行です。日付範囲が重複しており、互いに矛盾しています。2 行目は 1 が 2012 年 2 月 1 日から 123 年 3 月 1 日までの間「オン」であったことを主張していますが、3 行目は 1 が 2012 年 2 月 14 日より前にオフであったことを主張しています。同様に、2 行目は 1 が 02-MAR-12 にオフだったと主張していますが、3 行目はオンだったと主張しています。

私が適用したい調整ロジックは、矛盾が生じた場合に、可能な限り早い開始日とその後の可能な限り早い終了日を選択するというものです。したがって、結果は次のようになります。

Id    Begin_Date    End_date    
1     01-JAN-12     05-JAN-12
1     01-FEB-12     01-MAR-12

ラグ分析機能でこれをやってのけましたが、他のユースケースで苦労しました。この入力データセットを取得します。

Id    Begin_Date    End_date    
1     01-JAN-12     10-JAN-12
1     5-JAN-12      8-JAN-12
1     12-JAN-12     15-JAN-12
1     1-JAN-12      14-JAN-12

ここで出力として期待するのは次のとおりです。

Id    Begin_Date    End_date    
1     01-JAN-12     8-JAN-12
1     01-JAN-12     14-JAN-12

...最初の行が最も早い開始日であり、その終了日がその後の最も早い終了日であるためです。次の行は前の終了日の後の最も早い開始日であり、その行の終了日はその後の最も早い終了日です。2012 年 1 月 14 日以降の開始日はないので、これで終了です。

この問題を解決する運はほとんどありません。私が試したアプローチの 1 つは、ID で分割されたランクを取得し、それを最大ランクと比較することでした。次に、ラグ関数を使用して以前のランクと比較しました。ただし、この戦略は上記のユースケースでは完全に失敗します。

助言がありますか?

4

2 に答える 2

3

さて、重要な要件は次のとおりです。

私が適用したい調整ロジックは、矛盾が生じた場合に、可能な限り早い開始日とその後の可能な限り早い終了日を選択するというものです。

ここでsqlfiddle

CREATE TABLE table1
(
  id INT,
  DateStart DATE,
  DateEnd DATE
);

INSERT INTO table1
VALUES
(1, TO_DATE('20110101','YYYYMMdd'), TO_DATE('20110110','YYYYMMdd'));
INSERT INTO table1
VALUES
(2, TO_DATE('20110105','YYYYMMdd'), TO_DATE('20110108','YYYYMMdd'));
INSERT INTO table1
VALUES
(3, TO_DATE('20110112','YYYYMMdd'), TO_DATE('20110115','YYYYMMdd'));
INSERT INTO table1
VALUES
(4, TO_DATE('20110101','YYYYMMdd'), TO_DATE('20110114','YYYYMMdd'));
INSERT INTO table1
VALUES
(5, TO_DATE('20110206','YYYYMMdd'), TO_DATE('20110208','YYYYMMdd'));
INSERT INTO table1
VALUES
(6, TO_DATE('20110201','YYYYMMdd'), TO_DATE('20110207','YYYYMMdd'));

選択ステートメント:

SELECT ID, DATESTART, DATEEND
FROM 
(
  SELECT ID, TYPE, DATES AS DATESTART, 
         LEAD(DATES) OVER (ORDER BY DATES) AS DATEEND
  FROM
  (
    SELECT ID, TYPE,DATES,
      LAG(ID) OVER (ORDER BY DATES) AS LASTID,
      LAG(TYPE) OVER (ORDER BY DATES) AS LASTTYPE,
      LAG(DATES) OVER (ORDER BY DATES) AS LASTDATES
    FROM
    (
      SELECT ID,'START' AS TYPE,DATESTART AS DATES
      FROM table1
      UNION ALL
      SELECT ID,'END',DATEEND
      FROM table1
    )
  ) H
  WHERE TYPE != LASTTYPE OR LASTTYPE IS NULL
)
WHERE TYPE = 'START'
ORDER BY DATESTART

各サブクエリの手順は次のとおりです。

  1. 各行のdate startdate endを 1 つの列に分解する

  2. を使用して最後の行をコピーしLAG、現在の行に配置します

  3. 真ん中にある行を除外します (例: 1,2,3,4 は 2,3 を削除します)

    これらは最初または最後の行であるため、次の行の終了日を取得します

  4. 有用な行のみを抽出します。TYPE = START

于 2012-11-02T11:39:40.663 に答える
1

2 番目のデータ セットの場合:

Id    Begin_Date    End_date    
1     01-JAN-12     10-JAN-12
1     5-JAN-12      8-JAN-12
1     12-JAN-12     15-JAN-12
1     1-JAN-12      14-JAN-12

調整ロジックの後、結果は次のようになります。

Id    Begin_Date    End_date    
1     01-JAN-12     8-JAN-12 (includes the rows 1,2 and 4 -> minimum begin_date is 1-JAN, minimum end_date is 8-JAN)
1     12-JAN-12     15-JAN-12 (includes row 3)
于 2012-11-02T09:21:49.117 に答える