0

我对 SQL 有足够的了解,可以进行基本的和稍微高级的查询,但这就是我的知识结束的地方。

我有一个查询,其中涉及一系列复杂的函数调用,以将 JD Edwards ERP 应用程序“朱利安”日期转换为一年中的一周值。功能如下:

WEEK(DATE(CAST(CAST((1900 + JulianDate/1000) AS INTEGER) AS CHAR(4)) || '-01-01') + (MOD(JulianDate, 1000) - 1) DAYS)

WhereJulianDate是一列,其中的数值表示 JD Edwards 使用的儒略日期。格式为:CYYDDD,其中 C 是世纪,YY 是年份的最后 2 位,DDD 是一年中的第几天(1-366)。

这是在查询中的几个地方完成的,包括SELECT字段和GROUP BY字段。

这可行,但非常复杂,使 SQL 难以阅读和理解。此外,一些可以格式化 SQL 的工具由于某种原因无法处理这个问题,并将其留在未格式化的混乱中。

这是一个示例片段:

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)

问题

是否可以编写一个可以嵌入 SQL 的“函数”或“宏”(无论正确的术语是什么),然后在需要的地方“调用”?

如果我可以执行以下操作,那就太好了:

JulianToWeek(JulianDate) {
    return WEEK(DATE(CAST(CAST((1900 + JulianDate/1000) AS INTEGER) AS CHAR(4)) || '-01-01') + (MOD(JulianDate, 1000) - 1) DAYS)
}

然后使用它使上面的示例 SQL 更具可读性(并且不易出错):

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)

我已经阅读了一些关于 SQL 函数的内容,但它似乎是数据库中内置的东西。有没有办法做到这一点,它只是 SQL“代码”的一部分?

4

2 回答 2

1

创建函数非常简单。例如:

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
//

然后你可以使用它:

values julian2week(2020015);

结果:

1
-
3

或者在一个典型的SELECT

select d, julian2week(d) as w from jw;

结果:

      D  W
-------  -
2020015  3
2020032  6
于 2020-08-17T19:36:12.047 回答
1

我会创建一个函数来转换为 DATE,然后您可以WEEK()在 SQL 中使用或针对它的任何函数。所以

CREATE OR REPLACE FUNCTION DB_JDE_DATE(I INTEGER) 
    NO EXTERNAL ACTION
    DETERMINISTIC
RETURNS DATE
RETURN
    '1899-12-31'::DATE + (I/1000) YEARS + MOD(I, 1000) DAYS

顺便说一句,在调用 UDF 时,如果它不是在 中的模式中创建的,则需要使用它的模式名称对其进行限定CURRENT PATH,默认情况"SYSIBM","SYSFUN","SYSPROC","SYSIBMADM",X下 X 是CURRENT USER特殊寄存器的值。

于 2020-08-18T16:45:10.733 回答