我正在将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
我的转换有问题吗?还是错过了什么?
由于
答案 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步骤。
根据您的评论LFL
是bit
数据类型(0/1,TRUE / FALSE),因此CAST(MIN(CAST(s2.LFL as int)) as bit)
完全没用,并且您的结果集与{{ 1}}值如10。