I know enough about SQL to do basic and slightly more advanced queries, but that's about where my knowledge ends.
I have a query that involves a complex sequence of function calls to convert a JD Edwards ERP application "Julian" date to a week-of-year value. The function is as follows:
WEEK(DATE(CAST(CAST((1900 + JulianDate/1000) AS INTEGER) AS CHAR(4)) || '-01-01') + (MOD(JulianDate, 1000) - 1) DAYS)
Where JulianDate
is a column with a numeric value representing a Julian date that JD Edwards uses. The format is: CYYDDD, were C is the century, YY is the last 2 digits of the year, and DDD is the day of the year (1-366).
This is done in a couple of places in the query, including SELECT
fields and GROUP BY
fields.
This works, but is very complex and makes the SQL hard to read and understand. Also, some tools that can format the SQL, cannot handle this for some reason and leave it as an unformatted mess.
Here's an example snippet:
SELECT
F31122.WTMMCU AS BU,
F31122.WTMCU AS WC,
WEEK(DATE(CAST(CAST((1900 + F31122.WTDGL/1000) AS INTEGER) AS CHAR(4)) || '-01-01') + (MOD(F31122.WTDGL, 1000) - 1) DAYS) AS Week,
SUM(F31122.WTHRW) AS Hours
FROM PROD2DTA.F31122 AS F31122
WHERE
(F31122.WTTYR IN ('3')) AND
(F31122.WTDGL BETWEEN 120200 AND 120201)
GROUP BY
F31122.WTMMCU,
F31122.WTMCU,
WEEK(DATE(CAST(CAST((1900 + F31122.WTDGL/1000) AS INTEGER) AS CHAR(4)) || '-01-01') + (MOD(F31122.WTDGL, 1000) - 1) DAYS)
Question:
Is it possible to write a "function" or "macro" (whatever the correct term is) that can be embedded with the SQL and then "called" where needed?
It would be really nice if I could do something like the following:
JulianToWeek(JulianDate) {
return WEEK(DATE(CAST(CAST((1900 + JulianDate/1000) AS INTEGER) AS CHAR(4)) || '-01-01') + (MOD(JulianDate, 1000) - 1) DAYS)
}
And then use it to make the example SQL above a bit more readable (and less error prone):
SELECT
F31122.WTMMCU AS BU,
F31122.WTMCU AS WC,
JulianToWeek(F31122.WTDGL) AS Week,
SUM(F31122.WTHRW) AS Hours
FROM PROD2DTA.F31122 AS F31122
WHERE
(F31122.WTTYR IN ('3')) AND
(F31122.WTDGL BETWEEN 120200 AND 120201)
GROUP BY
F31122.WTMMCU,
F31122.WTMCU,
JulianToWeek(F31122.WTDGL)
I've read a little about SQL functions, but it seems like it's something that's built in" to the database. Is there a way to do this, where it's just part of the SQL "code"?
Creating the function is pretty easy. For example:
create function julian2week(in j integer) returns integer
language sql
begin
return week(date(cast(cast((1900 + j/1000) as integer) as char(4))
|| '-01-01') + (mod(j, 1000) - 1) days);
end
//
Then you can just use it:
values julian2week(2020015);
Result:
1
-
3
Or in a typical SELECT
:
select d, julian2week(d) as w from jw;
Result:
D W
------- -
2020015 3
2020032 6