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
;
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
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
5条答案
按热度按时间wh6knrhe1#
使用SQL可能会更简单。
您可以按原样运行这些语句以进行检查。
LAG函数使用
LAG
的问题是,如果你有非连续的日历,比如你的例子,并且某一天的CURRENT_DATE
(比如例子中的2022-07-24
)在那里不存在,你就不能使用它。顺便说一句,我不知道这是不是我的IBM i v7.5的问题,但是如果我把
WHERE
子句移到子选择中,我会得到错误的查询结果--它没有达到这里想要的目标,也没有返回预期的结果。聚合函数使用
不管日历中是否存在
CURRENT_DATE
都可以工作。ggazkfy82#
老实说,如果你需要某个日期的“前一个工作日”,你应该考虑在日历表中添加这样一列。
既然如此,不妨加上一个“下一个工作日”。
日历表的最大好处之一是能够预先计算这些列,从而大大简化了语句。
wsxa1bj13#
我不真实的清楚LAG的作用,因为我从来没有用过它。所以,这里有另一个使用交叉连接的解决方案:
交叉联接仅为日历文件中的每条记录返回一行,该行包含早于订单日期的最大工作日期。LATERAL仅允许子查询访问外部查询中的列。
ergxz8rk4#
编写一个名为
calndr_prevWorkDate
的SQL函数,该函数返回上一个工作日期。然后,在
SQL SELECT
语句的WHERE
子句中使用该函数从TRNHST
表中选择记录:下面是SQL函数。
wribegjk5#
如果你只需要一个表中的前一个日期,你可以使用类似的方法
从TRNHST中选择 *,其中事务处理日期=(从CALNDR中选择日历日期,其中日历日期〈当前日期,按日历日期说明限制1排序)