在 Teradata 中创建具有“with recursive”语句的递归视图

Posted

技术标签:

【中文标题】在 Teradata 中创建具有“with recursive”语句的递归视图【英文标题】:Create a recursive view that has a "with recursive" statement in Teradata 【发布时间】:2017-04-17 20:32:42 【问题描述】:

我想通过以下可重现的示例在 Teradata(即CREATE RECURSIVE VIEW)中创建递归视图:

CREATE VOLATILE TABLE vt1
(
    foo VARCHAR(10)
    , counter INTEGER
    , bar INTEGER
)
ON COMMIT PRESERVE ROWS;

INSERT INTO vt1 VALUES ('a', 1, '1');
INSERT INTO vt1 VALUES ('a', 2, '2');
INSERT INTO vt1 VALUES ('a', 3, '2');
INSERT INTO vt1 VALUES ('a', 4, '4');
INSERT INTO vt1 VALUES ('a', 5, '1');
INSERT INTO vt1 VALUES ('b', 1, '3');
INSERT INTO vt1 VALUES ('b', 2, '1');
INSERT INTO vt1 VALUES ('b', 3, '1');
INSERT INTO vt1 VALUES ('b', 4, '2');

WITH RECURSIVE cte (foo, counter, bar, rsum) AS
(
SELECT
    foo
  , counter
  , bar
  , bar AS rsum
FROM 
    vt1
QUALIFY ROW_NUMBER() OVER (PARTITION BY foo ORDER BY counter) = 1

UNION ALL

SELECT
    t.foo
  , t.counter
  , t.bar
  , CASE WHEN cte.rsum < 3 THEN t.bar + cte.rsum ELSE t.bar END
FROM
    vt1 t JOIN cte ON t.foo = cte.foo AND t.counter = cte.counter + 1
)

SELECT 
    cte.*
  , CASE WHEN rsum < 5 THEN 0 ELSE 1 END AS tester
FROM 
    cte
ORDER BY 
    foo
    , counter
;

这将创建此输出:

╔═════╦═════════╦═════╦══════╦════════╗
║ foo ║ counter ║ bar ║ rsum ║ tester ║
╠═════╬═════════╬═════╬══════╬════════╣
║ a   ║       1 ║   1 ║    1 ║      0 ║
║ a   ║       2 ║   2 ║    3 ║      0 ║
║ a   ║       3 ║   2 ║    5 ║      1 ║
║ a   ║       4 ║   4 ║    4 ║      0 ║
║ a   ║       5 ║   1 ║    5 ║      1 ║
║ b   ║       1 ║   3 ║    3 ║      0 ║
║ b   ║       2 ║   1 ║    4 ║      0 ║
║ b   ║       3 ║   1 ║    5 ║      1 ║
║ b   ║       4 ║   2 ║    2 ║      0 ║
╚═════╩═════════╩═════╩══════╩════════╝

我最终希望将其“保存”为视图。我试过CREATE RECURSIVE VIEW 和几个变种,但我想我不明白如何绕过WITH RECURSIVE cte 声明。

有关了解发生了什么的相关问题,请参阅this question

【问题讨论】:

语法为create recursive view ....。这是文档的链接:info.teradata.com/htmlPubs/DB_TTU_13_10/index.html#page/… 【参考方案1】:

好吧,这实际上比我想象的要难:

create recursive view db.test_view (
foo, counter,bar,rsum) as 
(SELECT
    foo,
    counter,
    bar,
    bar AS rsum
    FROM 
    vt1
    QUALIFY ROW_NUMBER() OVER (PARTITION BY foo ORDER BY counter) = 1

UNION ALL
SELECT
    t.foo,
    t.counter,
    t.bar,
    CASE WHEN cte.rsum < 5 THEN
        t.bar + cte.rsum
    ELSE t.bar 
    END
FROM
vt1 t
JOIN test_view cte
ON t.foo = cte.foo
AND t.counter = cte.counter + 1

)

不要限定视图的递归连接。即JOIN test_view,而不是JOIN db.test_view

【讨论】:

谢谢。我认为这很简单,并且在一个更复杂的问题的背景下,很高兴回到这个例子。 仍在苦苦挣扎——创建视图后,我无法访问。它说表vt1 不存在。有什么想法吗? 您是否尝试创建一个引用您问题中的易失性表的视图?我不确定你能做到这一点。您可以使用 GLOBAL TEMPORARY TABLE 或常规表。 视图当然可以引用 volatile 表,但正如@RobPaller 指出的那样,这没有任何意义,因为 volatile 表仅适用于您的会话。 @RobPaller,只要它们都在同一个会话中,它就对我有用。我其实有点惊讶。【参考方案2】:

易失性表存储在用户的假脱机空间配额中,应使用您的用户名进行限定。 附:你为什么首先使用 volatile 表?

【讨论】:

以上是关于在 Teradata 中创建具有“with recursive”语句的递归视图的主要内容,如果未能解决你的问题,请参考以下文章

从 .net 代码在 Teradata 中创建存储过程

在 SQL Server 2012 中创建以日期为范围分区的表

Teradata 中易失性表的光标

Teradata SQL 周数 - 从 1 月 1 日开始的第 1 周,周数与一周中的特定日期对齐

如何在 Teradata 数据库中查找所有具有特定列名的表?

在 teradata 14 中收集统计信息 - 不允许在同一组列上具有不同列排序的多个统计信息