db2 iSeries SQL -在JOIN标准中使用上一个记录值

h7wcgrx3  于 2022-11-07  发布在  DB2
关注(0)|答案(5)|浏览(156)

在我的示例中,我试图根据上一个日历工作日期从事务文件中检索记录。工作日期在名为CALNDR的文件中,事务在名为TRNHST的文件中。逻辑是使用CURRENT_DATE将光标设置在CALNDR上,然后检索上一个工作日期,它将用于连接到TRNHST.如果用RPG完成,这将足够简单,但我对SQL感到困惑.谢谢,你可以提供任何意见。
CALNDR
TRNHST

wh6knrhe

wh6knrhe1#

使用SQL可能会更简单。
您可以按原样运行这些语句以进行检查。

LAG函数使用

WITH 
  CALNDR (CALDT) AS
  (
    VALUES
      CAST ('2022-07-21' AS DATE)
    , CAST ('2022-07-22' AS DATE)
    , CAST ('2022-07-25' AS DATE)
  )
SELECT C.*
FROM
(
SELECT CALDT, LAG (CALDT) OVER (ORDER BY CALDT) AS LAG_CALDT
FROM CALNDR
) C
-- JOIN TRNHST ...

-- You must keep this expression in WHERE >>OUTSIDE<< of the subselect 
-- to get the desired result
WHERE C.CALDT = 
CAST ('2022-07-25' AS DATE)
--CAST ('2022-07-24' AS DATE)
;

LAG的问题是,如果你有非连续的日历,比如你的例子,并且某一天的CURRENT_DATE(比如例子中的2022-07-24)在那里不存在,你就不能使用它。
顺便说一句,我不知道这是不是我的IBM i v7.5的问题,但是如果我把WHERE子句移到子选择中,我会得到错误的查询结果--它没有达到这里想要的目标,也没有返回预期的结果。

聚合函数使用

WITH 
  CALNDR (CALDT) AS
  (
    VALUES
      CAST ('2022-07-21' AS DATE)
    , CAST ('2022-07-22' AS DATE)
    , CAST ('2022-07-25' AS DATE)
  )
SELECT C.*
FROM
(
SELECT MAX (CALDT) AS LAG_CALDT 
FROM CALNDR
WHERE CALDT < 
CAST ('2022-07-25' AS DATE)
--CAST ('2022-07-24' AS DATE)
) C
-- JOIN TRNHST
;

不管日历中是否存在CURRENT_DATE都可以工作。

ggazkfy8

ggazkfy82#

老实说,如果你需要某个日期的“前一个工作日”,你应该考虑在日历表中添加这样一列。
既然如此,不妨加上一个“下一个工作日”。
日历表的最大好处之一是能够预先计算这些列,从而大大简化了语句。

wsxa1bj1

wsxa1bj13#

我不真实的清楚LAG的作用,因为我从来没有用过它。所以,这里有另一个使用交叉连接的解决方案:

WITH calendar (workdt) AS (
    VALUES (CAST('2022-01-01' AS date)),
           (CAST('2022-02-01' AS date)),
           (CAST('2022-03-01' AS date)),
           (CAST('2022-04-01' AS date))
    ),
orders (orderno, orderdt) AS (
    VALUES (1, CAST('2022-01-15' AS date)),
           (2, CAST('2022-02-15' AS date)),
           (3, CAST('2022-03-15' AS date)),
           (4, CAST('2022-04-15' AS date))
    )
SELECT * 
FROM orders a
CROSS JOIN LATERAL (SELECT max(workdt) prevdt FROM calendar WHERE workdt < a.orderdt) b

交叉联接仅为日历文件中的每条记录返回一行,该行包含早于订单日期的最大工作日期。LATERAL仅允许子查询访问外部查询中的列。

ergxz8rk

ergxz8rk4#

编写一个名为calndr_prevWorkDate的SQL函数,该函数返回上一个工作日期。
然后,在SQL SELECT语句的WHERE子句中使用该函数从TRNHST表中选择记录:

select     a.*  
from       trnhst a                    
where      a.trandate = calndr_prevWorkDate( )

下面是SQL函数。

CREATE OR REPLACE FUNCTION calndr_prevWorkDate(                
startDate   date default current date )                        
RETURNS     date                                               
language sql                                                   
specific    calndrf1                                           
SET OPTION  datfmt = *ISO,   DLYPRP = *YES, DBGVIEW = *SOURCE, 
            USRPRF = *OWNER, DYNUSRPRF = *OWNER, COMMIT = *CHG 
BEGIN                                                          

declare     vCalDate  date ;                                   
declare     vSqlCode decimal(5,0) default 0 ;                  
declare     sqlCode int default 0 ;                            
declare     sqlState char(5) default ' ' ;                     
declare     vSqlState char(5) default ' ' ;                    
declare     vErrText varchar(256) default '' ;                 

DECLARE CONTINUE HANDLER FOR SQLEXCEPTION                      
begin                                                          
SET     vSqlCode  = SQLCODE ;                                  
SET     vSqlState = SQLstate ;                                 
get     diagnostics exception 1 vErrText = message_text ;      
end ;                                                          

select      a.caldate                                
into        vCalDate                                 
from        calndr a                                 
where       a.caldate < startDate                    
            and dayofweek(a.caldate) not in ( 1, 7)  
order by    a.caldate desc                           
fetch first row only ;                               

return      vCalDate ;                               
END
wribegjk

wribegjk5#

如果你只需要一个表中的前一个日期,你可以使用类似的方法
从TRNHST中选择 *,其中事务处理日期=(从CALNDR中选择日历日期,其中日历日期〈当前日期,按日历日期说明限制1排序)

相关问题