我正在尝试创建一个报告,显示使用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
因此,此“请求日期”(C6D0NB)字段在我的ERP系统(Infor XA)中标记为“日期”格式。我可以使用比较运算符来使用静态比较(例如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
返回:
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用于“请求日期”,
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 */
这真的是最简洁的编码方式吗?
谢谢!
答案 0 :(得分:1)
C6D0NB实际上不是Date列,它是一个数字列,其值由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数字。艾伦的包裹包括这样的功能......
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上的索引......
或者,您可以创建“日期”或“日历”表。除了使用它从数字日期转换为实际日期类型...它对许多其他基于集合的操作...在任何数据库中都很有用。
答案 1 :(得分:0)
不太关注CYYMMDD日期,但可以使用内置的varchar_format函数完成。
我从位置2进行比较,因为那是“1”,这是21世纪。
select * from mytable
where mycyymmdd date =
substring( varchar_format(current timestamp,'CCYY/MM/DD'), 2)
答案 2 :(得分:0)
从here复制只是为了方便查找:
由于所有变体都不符合我的需求,因此我提出了自己的变体。
这很简单:
select * from yourschema.yourtable where yourdate = int(CURRENT DATE - 1 days) - 19000000;
此days
可以识别leap年,并且适合大多数需求。
可以将days
更改为months
或years
。
不需要像VARCHAR_FORMAT
/ TIMESTAMP_FORMAT
这样的重型大炮。