In my example, I am trying to retrieve records from a transaction file based on the previous calendar work date. The work dates are in a file called CALNDR, the transactions in a file called TRNHST. The logic would be to use the CURRENT_DATE to set the cursor on CALNDR, then retrieve the previous work date which will be used to join to TRNHST. This would be simple enough if done in RPG but I am at a loss with SQL. Thanks, for any input you can provide.
This is even more simple with SQL probably.
You may uncomment the commented out block to run it as is to check.
/*
WITH
CALNDR (DT, IS_WORK) AS
(
VALUES
(CURRENT_DATE - 1 DAY, 'N')
, (CURRENT_DATE - 2 DAY, 'Y')
, (CURRENT_DATE - 3 DAY, 'Y')
)
, TRNHST (DT, SOME_COL) AS
(
VALUES
(CURRENT_DATE - 1 DAY, 1)
, (CURRENT_DATE - 2 DAY, 2)
, (CURRENT_DATE - 3 DAY, 3)
)
*/
SELECT CURRENT_DATE AS CDT, T.*
FROM
(
SELECT MAX (DT) DT
FROM CALNDR
WHERE DT < CURRENT_DATE AND IS_WORK = 'Y'
) C
JOIN TRNHST T ON T.DT = C.DT
Honestly, if "prior working day" for a given date is something you need. You should consider adding such a column to your calendar table.
While you're at it, might as well add a "next working day".
One of the biggest benefits to a calendar table is the ability to pre-calculate such columns. Thus, greatly simplifying your statements.
Not real sure what LAG does as I have never used it. So, here's another solution using a cross join:
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
The cross join only returns a single row for each record in the calendar file, and that row contains the largest work date less than the order date. LATERAL just lets the sub-query access columns from the outer query.
write an SQL function named calndr_prevWorkDate
that returns the previous work date.
Then use that function in the WHERE
clause of an SQL SELECT
statement to select records from the TRNHST
table:
select a.*
from trnhst a
where a.trandate = calndr_prevWorkDate( )
Here is the SQL function.
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
if all u need is the previous date from a table you can use something like that
select * from TRNHST where Trans_Date = ( select calendar_Date from CALNDR where calendar_Date < current date order by calendar_Date desc limit 1 )
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.