0

我无法让这个工作。我正在查询 S 表以获取项目列表,并希望加入 P 表以提取与 S + 前一个日期相同的日期的数据,只要可能使用了 LEAD 函数。

问题是 P 表很大,除非给出特定日期或小范围,否则需要永远查询。由于我是按日期加入标准普尔的,因此 LEAD 似乎无法提取前一个日期的数据。

还有其他选择吗?前面的 P.TDATE 通常只是之前的营业日期,但有时可能是一年多以前。

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 值。

是否有另一种基于 S.EDATE 而不是在左连接中使用 P.TDATE = S.EDATE 查询 P 表的有效方法?我相信这种情况是由于 LEAD 函数没有其他数据可查看而导致“先前”列上没有显示任何内容的原因。

谢谢,

4

4 回答 4

0

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

升学 | DESC 指定排序顺序(升序或降序)。ASC 是默认值。

NULLS FIRST | NULLS LAST 指定返回的包含空值的行应该出现在排序顺序中的第一个还是最后一个。

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

如果您由于 LEFT JOIN 而获得 NULL,您可以尝试将IGNORE NULLS选项添加到LEAD

       LEAD(P.TDATE IGNORE NULLS) OVER (PARTITION BY P.ID
                           ORDER BY P.TDATE DESC NULLS LAST) AS PRIOR_DATE,

这与

       LAG(P.TDATE IGNORE NULLS) OVER (PARTITION BY P.ID
                           ORDER BY P.TDATE) AS PRIOR_DATE,

或将计算移至派生表/内联视图:

SELECT S.ID,
       S.EDATE,
       S.PDATE,
       S.FACTOR,
       S.PTYPE,
       P.TDATE,
       P.PRICE,
       P.PTYPE,
       P.PRIOR_DATE,
       P.PRIOR_PRICE,
       P.PRIOR_PTYPE
FROM S
LEFT JOIN
 ( SELECT ...,
       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 P 
 ) 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:42:00.217 回答
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 回答
0

以叙述的形式思考这个问题:你在 S 中有一行。你想在 P 中找到两行:

  1. 直接匹配 S ID & EDATE 的 P 行。
  2. 您找到的第一个 P 行之前的行。

您实际上必须根据第一个 P 行找到第二个 P 行 - 它不能只是神奇地“在那里”让您通过正确的 LEAD() 化身向后走。

这样看,您试图找到最大 TDATE 小于 #1P 行的 TDATE 的 #2P 行。dnoeth 的答案是解决这个问题的一种方法——但正如你所见,它非常慢(他实际上正在构建与 S 中的任何 ID 匹配的所有 P 行的完整历史记录——如果不是针对 P 中的每个 ID——然后使用该构建的历史记录来“采摘" 找到#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 回答