DB2:您能否编写一个嵌入 SQL 的函数或宏来简化复杂的查询?

DB2: Can you write a function or macro emedded in the SQL to simplify a complex query?

我对 SQL 的了解足以进行基本和稍微高级的查询,但我的知识仅此而已。

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

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

其中 JulianDate 是一列,其数值表示 JD Edwards 使用的 Julian 日期。格式为: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“代码”的一部分?

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

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

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

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, which defaults to "SYSIBM","SYSFUN","SYSPROC","SYSIBMADM",X where X is the value of the CURRENT USER 特殊寄存器中的模式中创建的,则需要用它的模式名称来限定它。