Teradata外部申请

时间:2017-05-23 17:09:50

标签: teradata apply outer-join

我正在将MS SQL代码转换为Teradata并且已经提升了没有Teradata等效的OUTER APPLY。所以我在网上搜索,他们说它基本上是LEFT OUTER JOIN,但它可以让你有效地使用子查询。 我试图转换它,但我得到了不同的结果。 以下是代码

SQL

select 
    s.*,
    s2.NStartDate,
    s2.NextL 
from tDates s
outer apply (
        select 
        MIN(s2.StartDate)   NStartDate,
        CAST(MIN(CAST(s2.LFL as int)) as bit) NextL
        from tDates s2
        where
            s2.StoreNo = s.StoreNo
        and s2.StartDate > s.StartDate 
        and s2.LFL = case s.LFL when 0 then 1 else 0 end
    ) s2

TERADATA

SELECT
        s.*,
        s2.NStartDate, 
        s2.NextL
  FROM tDates s
  LEFT OUTER JOIN 
        (
            SELECT
                s2.StoreNo, 
                MIN(s2.StartDate) AS NStartDate, 
                CAST(MIN(CAST(s2.LFL AS  INTEGER)) AS  BYTEINT) AS NextL
            FROM tDates s2
            GROUP BY 
                s2.StoreNo
        ) s2
    ON s2.StoreNo = s.StoreNo
    AND s2.NStartDate > s.StartDate
    AND s2.NextL = CASE s.LFL WHEN 0 THEN 1 ELSE 0 END

输出

Outer Apply:
    o------o---------o--------------o-------o
    |StoreN|  SCode  | NStartDate   | NextL |
    o------o---------o--------------o-------o
    |   1  |   A     | 2016-01-13   |  10   |
    |   1  |   A     | 2016-01-12   |  20   |
    |   2  |   B     | 2016-01-08   |  40   |
    |   2  |   B     | 2016-01-06   |  30   |
    |   3  |   C     |   NULL       |  NULL |
    o------o---------o--------------o-------o

Left Outer Join:
    o------o---------o--------------o-------o
    |StoreN|  SCode  | NStartDate   | NextL |
    o------o---------o--------------o-------o
    |   1  |   A     | 2016-01-13   |  10   |
    |   1  |   A     | 2016-01-12   |  20   |
    |   2  |   B     |   NULL       |  NULL |
    |   3  |   C     |   NULL       |  NULL |
    o------o---------o--------------o-------o

我的转换有问题吗?还是错过了什么?

由于

1 个答案:

答案 0 :(得分:0)

OUTER APPLY是Microsoft对标准SQL的LATERAL JOIN的实现,它是一种相关联接。当它返回单行时(如MIN),它可以被相关标量子查询替换,每列一个,但性能会很差。

当您访问同一个表两次时,最好的重写将基于分析函数,尽管s2.LFL = case s.LFL when 0 then 1 else 0 end有点棘手:

SELECT 
   s.*,
   CASE
      WHEN LFL=0 
           -- only check LFL 1 for the minimum date
      THEN Min(CASE WHEN LFL = 1 THEN StartDate END)
           Over (PARTITION BY StoreNo
                 ORDER BY StartDate
                 ROWS BETWEEN 1 Following AND Unbounded Following)
      ELSE -- only check LFL 0 for the minimum date
           Min(CASE WHEN LFL = 0 THEN StartDate END)
           Over (PARTITION BY StoreNo
                 ORDER BY StartDate
                 ROWS BETWEEN 1 Following AND Unbounded Following)
   END AS NStartDate,

   -- repeated logic, one for each column
   -- returns 0/1/NULL -> doesn't match your result set
   CASE
      WHEN LFL=0
      THEN Min(CASE WHEN LFL = 1 THEN LFL END)
           Over (PARTITION BY StoreNo
                 ORDER BY StartDate
                 ROWS BETWEEN 1 Following AND Unbounded Following)
      ELSE Min(CASE WHEN LFL = 0 THEN LFL END)
           Over (PARTITION BY StoreNo
                 ORDER BY StartDate
                 ROWS BETWEEN 1 Following AND Unbounded Following)
    END AS NextL
FROM tDates s

这应该在Explain中产生一个STATS步骤。

根据您的评论LFLbit数据类型(0/1,TRUE / FALSE),因此CAST(MIN(CAST(s2.LFL as int)) as bit)完全没用,并且您的结果集与{{ 1}}值如10。