0

これを機能させるのに問題があります。S テーブルにクエリを実行してアイテムのリストを取得し、P テーブルに結合して、LEAD 関数を使用している可能性がある場合はいつでも、S と同じ日付 + 前の日付のデータを取得したいと考えています。

問題は、P テーブルが巨大で、特定の日付または小さな範囲が指定されない限り、クエリに永遠に時間がかかることです。私は日付で S & P に参加しているので、LEAD は前の日付のデータを引き出すことに取り組んでいないようです。

別のオプションはありますか?前の P.TDATE は多くの場合、前の営業日ですが、1 年以上前の場合もあります。

SELECT S.ID,
       S.EDATE,
       S.PDATE,
       S.FACTOR,
       S.PTYPE,
       P.TDATE,
       P.PRICE,
       P.PTYPE,
       LEAD(P.TDATE) OVER (PARTITION BY P.ID
                           ORDER BY P.TDATE DESC) AS PRIOR_DATE,
       LEAD(P.PRICE) OVER (PARTITION BY P.ID
                           ORDER BY P.TDATE DESC) AS PRIOR_PRICE,
       LEAD(P.PTYPE) OVER (PARTITION BY P.ID
                           ORDER BY P.TDATE DESC) AS PRIOR_PTYPE
FROM S
LEFT JOIN P ON P.ID = S.ID
AND P.TDATE = S.EDATE
WHERE S.PERIOD = 'D'
  AND S.PTYPE IN ('A',
                  'G',
                  'Q',
                  'Y')
ORDER BY S.EDATE ;

私はすべての適切なデータを取得していますが、prior_date、prior_price、およびprior_ptypeがすべて空白であってはならない場合を除きます。

日付フィールドに NULL 値はありません。

左結合で P.TDATE = S.EDATE を使用するのではなく、S.EDATE に基づいて P テーブルをクエリする別の効率的な方法はありますか? LEAD 関数には他に調べるデータがないため、この状態が「前の」列に何も表示されない原因であると思います。

ありがとう、

4

4 に答える 4

0

http://docs.oracle.com/cd/E11882_01/server.112/e41084/functions004.htm#SQLRF06174

ASC | DESC 順序付け順序 (昇順または降順) を指定します。ASC がデフォルトです。

NULL ファースト | NULLS LAST 返された null を含む行を順序付け順序の最初または最後に表示するかどうかを指定します。

NULLS LAST は昇順のデフォルトであり、NULLS FIRST は降順のデフォルトです。

分析関数は常に、関数の order_by_clause で指定された順序で行を操作します。ただし、関数の order_by_clause は、結果の順序を保証しません。クエリの order_by_clause を使用して、最終結果の順序を保証します。

    SELECT S.ID,
           S.EDATE,
           S.PDATE,
           S.FACTOR,
           S.PTYPE,
           P.TDATE,
           P.PRICE,
           P.PTYPE,
           LEAD(P.TDATE) OVER (PARTITION BY P.ID
                               ORDER BY P.TDATE DESC NULLS LAST) AS PRIOR_DATE,
           LEAD(P.PRICE) OVER (PARTITION BY P.ID
                               ORDER BY P.TDATE DESC NULLS LAST) AS PRIOR_PRICE,
           LEAD(P.PTYPE) OVER (PARTITION BY P.ID
                               ORDER BY P.TDATE DESC NULLS LAST) AS PRIOR_PTYPE
    FROM S
    LEFT JOIN P ON P.ID = S.ID
    AND P.TDATE = S.EDATE
    WHERE S.PERIOD = 'D'
      AND S.PTYPE IN ('A',
                      'G',
                      'Q',
                      'Y')
    ORDER BY S.EDATE ;
于 2015-10-13T17:21:02.553 に答える
0

これを物語形式で考えてみましょう: S に行があります。P に 2 つの行を見つけたいとします。

  1. S ID と EDATE が直接一致する P 行。
  2. 最初に見つけた P 行の直前の行。

実際には、最初の P 行に基づいてその 2 番目の P 行を見つける必要があります。LEAD() の正しい化身で逆戻りするために魔法のように「そこにいる」ことはできません。

そのように見ると、#1P 行の TDATE よりも小さい最大 TDATE を持つ #2P 行を見つけようとしています。dnoeth の答えはこれに対する 1 つのアプローチですが、ご覧のとおり、非常に遅いです (彼は実際には、S の任意の ID に一致するすべての P 行の完全な履歴を構築しています。 " #1P 行を見つけた後に #2P 行)。

これは、特に P が ID と TDATE の両方でインデックス付けされている場合は、より適切なアプローチである必要があります。

SELECT T.*  , P3.PRICE PRIOR_PRICE, P3.PTYPE PRIOR_PTYPE
FROM 
    (
    SELECT S.ID,
           S.EDATE,
           S.PDATE,
           S.FACTOR,
           S.PTYPE S_PTYPE,
           P.TDATE,
           P.PRICE,
           P.PTYPE P_PTYPE,
           (SELECT MAX(P2.TDATE)  FROM P P2 WHERE P2.ID = P.ID AND P2.TDATE < P.TDATE) PRIOR_TDATE
    FROM S
    LEFT JOIN P ON P.ID = S.ID
    AND P.TDATE = S.EDATE
    WHERE S.PERIOD = 'D'
      AND S.PTYPE IN ('A','G','Q','Y')
    ) T
LEFT JOIN P P3 ON P3.ID = T.ID AND P3.TDATE = T.PRIOR_TDATE
ORDER BY T.EDATE ;
于 2015-10-13T19:23:55.517 に答える
0

ケースを再現するために次のクエリを調整できますか

WITH a
     AS (SELECT 1 id, TO_DATE ('01-01-2011', 'mm-dd-yyyy') dat, 0 val
           FROM DUAL
         UNION ALL
         SELECT 1 id, TO_DATE ('01-02-2011', 'mm-dd-yyyy') dat, 1 val
           FROM DUAL
         UNION ALL
         SELECT 2 id, TO_DATE ('01-03-2011', 'mm-dd-yyyy') dat, 2 val
           FROM DUAL)
SELECT id, dat, val, LEAD (val) OVER (PARTITION BY id ORDER BY dat DESC) pre_val
  FROM a
于 2015-10-13T17:14:15.990 に答える