比较DB2 DATES - IBM i日期与DB2日期SQL不兼容

时间:2018-02-12 22:40:44

标签: sql date db2 comparison-operators

我正在尝试创建一个报告,显示使用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 */ 

这真的是最简洁的编码方式吗?

谢谢!

3 个答案:

答案 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更改为monthsyears。 不需要像VARCHAR_FORMAT / TIMESTAMP_FORMAT这样的重型大炮。