比较 DB2 日期 - IBM i 日期与 DB2 日期不兼容 SQL
Comparing DB2 DATES - IBM i dates not compatible with DB2 dates SQL
我正在尝试创建一个报告,显示延迟的订单、当月到期的、下个月到期的等。使用 DB2 SQL 从 IBM i 服务器 (AS/400) 中提取数据。但是,我 运行 正在处理比较运算符的问题。我有一个潜在的解决方案,但它非常乏味,以至于会使我的代码明显变长并且很容易出错。
例如,我正在按请求日期拉取客户订单:
SELECT C6D0NB /* REQUEST DATE */
FROM MBC6REP /* CUSTOMER ORDER FILE */
WHERE C6DCCD = '1' /* ONLY ORDERS, NOT QUOTES */
ORDER BY C6D0NB DESC /* DATES DESCENDING ORDER */
这导致:
Request
date
118/08/28
118/06/29
118/06/15
118/06/07
....
117/07/21
117/06/14
117/04/14
117/03/01
因此,此 "Request Date" (C6D0NB) 字段在我的 ERP 系统 (Infor XA) 中被标记为 "date" 格式。我可以使用比较运算符来使用静态比较(例如,在 2018 年 1 月 1 日和 2018 年 1 月 15 日之间,包括在内):
SELECT C6D0NB /* REQUEST DATE */
FROM MBC6REP /* CUSTOMER ORDER FILE */
WHERE C6DCCD = '1' /* ONLY ORDERS, NOT QUOTES */ AND
C6D0NB >= '1180101' AND
C6D0NB <= '1180115'
ORDER BY C6D0NB DESC /* DATES DESCENDING ORDER */
结果:
Request
date
118/01/15
118/01/15
118/01/12
118/01/12
....
118/01/03
118/01/03
118/01/03
118/01/02
但是,当我想使用"CURRENT DATE"函数时,我运行就出错了。当我查询时:
SELECT CURRENT DATE
FROM SYSIBM.SYSDUMMY1
我收到了预期的:
CURRENT DATE
02/12/18
我可以按预期使用 DAY、MONTH、YEAR 函数:
SELECT DAY(CURRENT DATE)
FROM SYSIBM.SYSDUMMY1
哪个returns:
DAY
12
但是我不能将两者结合起来:
SELECT C6D0NB /* REQUEST DATE */
FROM MBC6REP /* CUSTOMER ORDER FILE */
WHERE C6DCCD = '1' /* ONLY ORDERS, NOT QUOTES */ AND
C6D0NB >= CURRENT DATE
ORDER BY C6D0NB DESC /* DATES DESCENDING ORDER */
这给了我错误:
Comparison operator >= operands not compatible.
如果我尝试将 MONTH 与 "Request Date"、
一起使用
SELECT MONTH(C6D0NB) /* REQUEST DATE */
FROM MBC6REP /* CUSTOMER ORDER FILE */
WHERE C6DCCD = '1' /* ONLY ORDERS, NOT QUOTES */
ORDER BY C6D0NB DESC /* DATES DESCENDING ORDER */
我收到此错误:
Argument 1 of function MONTH not valid.
如何创建一个动态报表来查询,例如,当月的所有日期?我可以 运行 下面的代码,但它非常乏味:
SELECT C6D0NB /* REQUEST DATE */
FROM MBC6REP /* CUSTOMER ORDER FILE */
WHERE C6DCCD = '1' /* ONLY ORDERS, NOT QUOTES */ AND
MONTH(TO_DATE((CONCAT(
CONCAT(
(CONCAT(SUBSTRING(C6D0NB,4,2), '/')),
(CONCAT(SUBSTRING(C6D0NB,6,2), '/'))),
SUBSTRING(C6D0NB,2,2))), 'MM/DD/YY')) = MONTH(CURRENT DATE) AND
YEAR(TO_DATE((CONCAT(
CONCAT(
(CONCAT(SUBSTRING(C6D0NB,4,2), '/')),
(CONCAT(SUBSTRING(C6D0NB,6,2), '/'))),
SUBSTRING(C6D0NB,2,2))), 'MM/DD/YY')) = YEAR(CURRENT DATE)
ORDER BY C6D0NB DESC /* DATES DESCENDING ORDER */
这真的是最简洁的编码方式吗?
谢谢!
C6D0NB 实际上不是日期列,它是一个数值列,您的 ERP 将其值解释为 CYYMMDD 格式的日期。
IBM i 及其前身 iSeries 和 AS/400 长期以来一直支持真正的日期类型。
遗憾的是,许多较旧的应用程序并未使用它们...
最佳解决方案,使用 UDF 将数值转换为实际日期。您可以自己编写或下载 Alan Campin 的 iDate 工具...
然后你就可以简单地做...
SELECT C6D0NB /* REQUEST DATE */
FROM MBC6REP /* CUSTOMER ORDER FILE */
WHERE C6DCCD = '1' /* ONLY ORDERS, NOT QUOTES */ AND
idate(C6D0NB,'*CYMD') >= CURRENT DATE
ORDER BY C6D0NB DESC /* DATES DESCENDING ORDER */
实际上,从性能的角度来看,将日期转换为 CYYMMDD 数字会更好。 Alan的包里有这样一个功能...
SELECT C6D0NB /* REQUEST DATE */
FROM MBC6REP /* CUSTOMER ORDER FILE */
WHERE C6DCCD = '1' /* ONLY ORDERS, NOT QUOTES */ AND
C6D0NB >= convertToiDate(CURRENT DATE, '*CYMD')
ORDER BY C6D0NB DESC /* DATES DESCENDING ORDER */
这允许使用 C6D0NB 上的索引...
或者,您可以创建 "Dates" 或 "Calendar" Table。除了使用它将数字日期转换为实际日期类型之外……它对许多其他基于集合的操作很有用……在任何数据库中。
CYYMMDD 日期不太好看,但可以使用内置 varchar_format 函数完成。
我是从位置 2 开始比较的,因为那里是“1”,这是 21 世纪。
select * from mytable
where mycyymmdd date =
substring( varchar_format(current timestamp,'CCYY/MM/DD'), 2)
从 复制只是为了方便查找:
由于 none 种变体满足了我的需要,所以我推出了自己的变体。
就这么简单:
select * from yourschema.yourtable where yourdate = int(CURRENT DATE - 1 days) - 19000000;
这 days
是飞跃 year-aware 并且适合大多数需要。
同样的方法days
可以变成months
或years
。
不需要VARCHAR_FORMAT
/TIMESTAMP_FORMAT
.
这样的重炮
我正在尝试创建一个报告,显示延迟的订单、当月到期的、下个月到期的等。使用 DB2 SQL 从 IBM i 服务器 (AS/400) 中提取数据。但是,我 运行 正在处理比较运算符的问题。我有一个潜在的解决方案,但它非常乏味,以至于会使我的代码明显变长并且很容易出错。
例如,我正在按请求日期拉取客户订单:
SELECT C6D0NB /* REQUEST DATE */
FROM MBC6REP /* CUSTOMER ORDER FILE */
WHERE C6DCCD = '1' /* ONLY ORDERS, NOT QUOTES */
ORDER BY C6D0NB DESC /* DATES DESCENDING ORDER */
这导致:
Request
date
118/08/28
118/06/29
118/06/15
118/06/07
....
117/07/21
117/06/14
117/04/14
117/03/01
因此,此 "Request Date" (C6D0NB) 字段在我的 ERP 系统 (Infor XA) 中被标记为 "date" 格式。我可以使用比较运算符来使用静态比较(例如,在 2018 年 1 月 1 日和 2018 年 1 月 15 日之间,包括在内):
SELECT C6D0NB /* REQUEST DATE */
FROM MBC6REP /* CUSTOMER ORDER FILE */
WHERE C6DCCD = '1' /* ONLY ORDERS, NOT QUOTES */ AND
C6D0NB >= '1180101' AND
C6D0NB <= '1180115'
ORDER BY C6D0NB DESC /* DATES DESCENDING ORDER */
结果:
Request
date
118/01/15
118/01/15
118/01/12
118/01/12
....
118/01/03
118/01/03
118/01/03
118/01/02
但是,当我想使用"CURRENT DATE"函数时,我运行就出错了。当我查询时:
SELECT CURRENT DATE
FROM SYSIBM.SYSDUMMY1
我收到了预期的:
CURRENT DATE
02/12/18
我可以按预期使用 DAY、MONTH、YEAR 函数:
SELECT DAY(CURRENT DATE)
FROM SYSIBM.SYSDUMMY1
哪个returns:
DAY
12
但是我不能将两者结合起来:
SELECT C6D0NB /* REQUEST DATE */
FROM MBC6REP /* CUSTOMER ORDER FILE */
WHERE C6DCCD = '1' /* ONLY ORDERS, NOT QUOTES */ AND
C6D0NB >= CURRENT DATE
ORDER BY C6D0NB DESC /* DATES DESCENDING ORDER */
这给了我错误:
Comparison operator >= operands not compatible.
如果我尝试将 MONTH 与 "Request Date"、
一起使用 SELECT MONTH(C6D0NB) /* REQUEST DATE */
FROM MBC6REP /* CUSTOMER ORDER FILE */
WHERE C6DCCD = '1' /* ONLY ORDERS, NOT QUOTES */
ORDER BY C6D0NB DESC /* DATES DESCENDING ORDER */
我收到此错误:
Argument 1 of function MONTH not valid.
如何创建一个动态报表来查询,例如,当月的所有日期?我可以 运行 下面的代码,但它非常乏味:
SELECT C6D0NB /* REQUEST DATE */
FROM MBC6REP /* CUSTOMER ORDER FILE */
WHERE C6DCCD = '1' /* ONLY ORDERS, NOT QUOTES */ AND
MONTH(TO_DATE((CONCAT(
CONCAT(
(CONCAT(SUBSTRING(C6D0NB,4,2), '/')),
(CONCAT(SUBSTRING(C6D0NB,6,2), '/'))),
SUBSTRING(C6D0NB,2,2))), 'MM/DD/YY')) = MONTH(CURRENT DATE) AND
YEAR(TO_DATE((CONCAT(
CONCAT(
(CONCAT(SUBSTRING(C6D0NB,4,2), '/')),
(CONCAT(SUBSTRING(C6D0NB,6,2), '/'))),
SUBSTRING(C6D0NB,2,2))), 'MM/DD/YY')) = YEAR(CURRENT DATE)
ORDER BY C6D0NB DESC /* DATES DESCENDING ORDER */
这真的是最简洁的编码方式吗?
谢谢!
C6D0NB 实际上不是日期列,它是一个数值列,您的 ERP 将其值解释为 CYYMMDD 格式的日期。
IBM i 及其前身 iSeries 和 AS/400 长期以来一直支持真正的日期类型。
遗憾的是,许多较旧的应用程序并未使用它们...
最佳解决方案,使用 UDF 将数值转换为实际日期。您可以自己编写或下载 Alan Campin 的 iDate 工具...
然后你就可以简单地做...
SELECT C6D0NB /* REQUEST DATE */
FROM MBC6REP /* CUSTOMER ORDER FILE */
WHERE C6DCCD = '1' /* ONLY ORDERS, NOT QUOTES */ AND
idate(C6D0NB,'*CYMD') >= CURRENT DATE
ORDER BY C6D0NB DESC /* DATES DESCENDING ORDER */
实际上,从性能的角度来看,将日期转换为 CYYMMDD 数字会更好。 Alan的包里有这样一个功能...
SELECT C6D0NB /* REQUEST DATE */
FROM MBC6REP /* CUSTOMER ORDER FILE */
WHERE C6DCCD = '1' /* ONLY ORDERS, NOT QUOTES */ AND
C6D0NB >= convertToiDate(CURRENT DATE, '*CYMD')
ORDER BY C6D0NB DESC /* DATES DESCENDING ORDER */
这允许使用 C6D0NB 上的索引...
或者,您可以创建 "Dates" 或 "Calendar" Table。除了使用它将数字日期转换为实际日期类型之外……它对许多其他基于集合的操作很有用……在任何数据库中。
CYYMMDD 日期不太好看,但可以使用内置 varchar_format 函数完成。
我是从位置 2 开始比较的,因为那里是“1”,这是 21 世纪。
select * from mytable
where mycyymmdd date =
substring( varchar_format(current timestamp,'CCYY/MM/DD'), 2)
从
由于 none 种变体满足了我的需要,所以我推出了自己的变体。
就这么简单:
select * from yourschema.yourtable where yourdate = int(CURRENT DATE - 1 days) - 19000000;
这 days
是飞跃 year-aware 并且适合大多数需要。
同样的方法days
可以变成months
或years
。
不需要VARCHAR_FORMAT
/TIMESTAMP_FORMAT
.