【问题标题】:DB2 recursive UDF TableDB2 递归 UDF 表
【发布时间】:2016-12-05 15:17:03
【问题描述】:

我在 DB2 中编写递归表函数时遇到问题。

我有一个值表....

With t (Adjustment) as (
VALUES (100)
    , (200)
    , (300)
) select * from t;

我需要向 UDF 表函数传递一个开始值(比如 5000)和一个因子(比如 0.1)

我需要显示如下结果....

Opening Shift   Adjustment  Closing
(3)     (1)     (2)
==================================================
5000    500     100     5600            
5600    560     200     6360
6360    636     300     7296
  1. Shift = 打开 * 0.1
  2. 关闭 = 打开 + Shift + 关闭
  3. 开头是上一行的结尾

我的递归函数在我尝试将前移时卡住了……(SQL0345N 递归公用表表达式的全查询)

感谢任何想法如何做到这一点。我知道存储过程可以做到这一点,但我需要使用 UDF 以便它可以在另一个 UDF 中扩展。

【问题讨论】:

  • 什么定义了表 T 中数据的排序规则,以便确定上一行; row_number() over() 也许没有特定的顺序?另外,2)在OP中定义为Opening + Shift + Closing,但显然,根据结果,表达式应该是`Opening + Shift + Adjustment`

标签: sql recursion db2


【解决方案1】:

我不确定我是否正确地解释了这个场景,但这是我所做的:

首先,我将创建几个变量来模拟函数的输入,然后编写一个递归公用表表达式 (RCTE) 以使用从这些变量中获得的数据生成报告:

 create variable OpenedWith decimal     default 5000    
 ;
 create variable Factor     decimal(2, 1) default 0.1   
 ;


 with                                                           
   t (adjustment) as ( values(100), (200), (300) )              
 , ordRows (rn, Adjustment ) as                                 
    ( select row_number() over(), Adjustment from t )           
 , addRows (rn, Opening, Shift, Adjustment, closing ) as        
    ( select rn, OpenedWith, OpenedWith*Factor , Adjustment     
           , ( OpenedWith + ( OpenedWith*Factor ) + Adjustment )
      from ordRows                                              
      where rn = 1                                              
    union all                                                   
      select b.rn, a.Closing, a.Closing * Factor , b.Adjustment 
           , ( a.Closing + (a.Closing * Factor) + b.Adjustment )
      from addRows a                                            
      join ordRows b                                            
        on a.rn = ( b.rn - 1 )                                  
    )                                                           
 select int(rn) as rn, int(opening) as opening
      , int(shift) as shift, adjustment       
      , int(closing) as closing               
 from addRows                                 


以下是上述查询的报告:

 RN         OPENING           SHIFT      ADJUSTMENT         CLOSING
  1           5,000             500             100           5,600
  2           5,600             560             200           6,360
  3           6,360             636             300           7,296

现在修改上面的脚本变量创建和查询到一个用户定义的表函数(UDTF),它对名为 T 的 TABLE 中的数据进行操作:

 create function shifted_vals  
  ( OpenedWith decimal( 5 )    
  , Factor     decimal( 3, 2)  
  )                            
  returns table                
  ( Opening      int           
  , Shift        int           
  , Adjustment   int           
  , Closing      int           
  )                            
 return                        
 with                          
   ordRows (rn, Adjustment ) as
    ( select row_number() over(), Adjustment from t )           
 , addRows (rn, Opening, Shift, Adjustment, closing ) as        
    ( select rn, OpenedWith, OpenedWith*Factor , Adjustment     
           , ( OpenedWith + ( OpenedWith*Factor ) + Adjustment )
      from ordRows                                              
      where rn = 1                                              
    union all                                                   
      select b.rn, a.Closing, a.Closing * Factor , b.Adjustment 
           , ( a.Closing + (a.Closing * Factor) + b.Adjustment )
      from addRows a                                            
      join ordRows b                                            
        on a.rn = ( b.rn - 1 )                                  
    )                                                           
 select opening, shift, adjustment, closing                     
 from addRows                                                   
 order by rn                                                    


现在调用 UDTF 并使用注明的开盘值和因子作为参数;即不再依赖于创建的变量,而是通过输入参数获得的值:

select t.*                              
from table(shifted_vals(5000, 0.1)) as t
; -- results as report, follows:
  OPENING           SHIFT      ADJUSTMENT         CLOSING
    5,000             500             100           5,600
    5,600             560             200           6,360
    6,360             636             300           7,296

【讨论】:

  • 感谢 CRPence。当我运行您的第一个查询时,我遇到了一个错误... SQL0345N 递归公用表表达式“.ADDROWS”的全查询必须是两个或多个全查询的 UNION,并且不能包含列函数、GROUP BY 子句、HAVING子句、ORDER BY 子句或包含 ON 子句的显式连接。
  • 有效!! CRPence 我只需要删除 ON 子句... union all select b.rn, a.Closing, a.Closing * 0.1 , b.Adjustment, ( a.Closing + (a.Closing * 0.1) + b.Adjustment )来自 addRows a, ordRows b 其中 a.rn = ( b.rn - 1 )
  • 啊! DB2 变体的那些细微差别,以及没有标记来说明正在使用哪个。我应该注意到我使用的是哪个;所示的 JOIN 语法在运行这些查询的 DB2 for i SQL 上是可接受的,并且在 IBM i 7.1 上产生了所示的输出,除非您另有建议 [例如我编辑答案],我将允许这些 cmets 为遇到错误的任何人提供帮助。
猜你喜欢
  • 2021-05-28
  • 1970-01-01
  • 2023-03-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-07-16
  • 1970-01-01
相关资源
最近更新 更多