2014-09-22 50 views
0

我试图返回将在下个月到期的我的CARD表的卡。但问题是该表有两列来表示卡的日期。列是EXPIREDAY和EXPIREMONTH,都是数字。所以,当我做到这一点查询我得到一个错误:如何将oracle中的sysdate月份值转换为数字?

select * from CARD WHERE EXPIREDAY <= sysdate - interval '2' DAY; 
    //Oracle error: ORA-00932: inconsistent datatypes: expected NUMBER got DATE 

有没有办法给sysdate - interval '2' DAY为数字数据类型转换?

谢谢!

+2

你为什么要在单独的列中保存日期和月份,并且你还有一年的专栏?你的2天间隔调整似乎与你所说的你想做的事情不符 - 在下个月寻找“日期”?是在10月的任何时候,还是从现在到10月22日? – 2014-09-22 14:38:21

+0

@AlexPoole数据库是第三个,所以我无法控制它。而2天的时间间隔就是一个例子,你可以把所需的一切都放在那个查询中。 – gog 2014-09-22 14:41:26

回答

1

尝试使用to_char(sysdate - interval '2' DAY,'ddmmyyyy')转换为字符类型。日期格式(“DDMMYYYY”)将依赖的expiredate

+0

谢谢。我做到了。但是,有没有办法让我在查询之外测试这个函数to_char(sysdate - interval'2'DAY,'ddmmyyyy')?只是为了看到它返回给我的结果? – gog 2014-09-22 14:48:14

+0

对不起,我不明白“查询之外”部分。你的意思是plsql? – Aramillo 2014-09-22 14:54:54

+0

@Aramillo - 你的意思是:'select to_char(sysdate - interval'2'DAY,'ddmmyyyy')from dual;''如果你打算比较字符串,那么使用'yyyymmdd'格式会更容易,并且将两列以相同的格式结合起来 - 在选择最合适的年份时也会遇到同样的问题。 – 2014-09-22 15:06:47

2

价值的。如果要比较的值作为字符串,你可以用它来对SYSDATE

SELECT TO_CHAR(sysdate, 'MM') || TO_CHAR(sysdate, 'DD') MONTH_NUM FROM DUAL 
-- gives you "0922" 

转换,这对于您的数字列其中将与前导零垫,如果你只有一个单一的数字

SELECT TO_CHAR(9, 'FM00') || TO_CHAR(22, 'FM00') MONTH_NUM FROM DUAL 
-- also gives you "0922" 

如果你有在表模式控制这将是存储在一个单一的数字字段两个星期和月份值的最佳实践,使9- SEP将作为num存储在此列中eric value 0922其中月份是第一个,以便使用自然排序。

2

一个简单而不一定是非常有效的方法是日期和月份值转换为实际日期,使用to_date(),然后比较,与你的目标日期范围:

select * from card 
where to_date(lpad(expireday, 2, '0') 
    ||'/'|| lpad(expiremonth, 2, '0'), 'DD/MM') 
between sysdate and add_months(sysdate, 1); 

Which appears to work。但是如果日期跨越年底,这将会有问题。由于您的表格未指定年份,因此您必须先完成一项工作,或允许to_date将其默认为当前年份。如果你让它默认,那么它将无法工作。例如,如果您的表格中包含12月和1月的值,并在12月运行此查询,则1月日期将被视为2014年1月,并且不会计入下个月。所以你需要做更多的选择合适的一年。

这在当前为下一个年,这可能是配不上你,你只需要一个月的窗口前,把任何一个月份的数字:使用从日期范围

select * from card 
where to_date(lpad(expireday, 2, '0') 
    ||'/'|| lpad(expiremonth, 2, '0') 
    ||'/'|| (extract(year from sysdate) + 
    case when expiremonth < extract(month from sysdate) then 1 else 0 end), 
    'DD/MM/YYYY') 
between sysdate and add_months(sysdate, 1); 

SQL Fiddle十二月至一月。

而且你可以看到两列合并的方式形成日期in this Fiddle

像往常一样,道德是......将事物存储为正确的数据类型。将日期存储为日期,而不是字符串或数字。

2

Im trying to return the CARDS of my CARD table that will expire in the next month. But the problem is that the table has two columns to represent the card date.

假设:

  1. 要使用浮动个月(比如:从12月23日至1月23日)和
  2. 你的表不知何故只包含一个(浮动?)年的数据

为什么你不能使用简单的算术?这样的:

-- some constant definitions for testing purpose 
with cst as (
    select EXTRACT(DAY from TO_DATE('23/12','DD/MM')) as theDay, 
     EXTRACT(MONTH from TO_DATE('23/12','DD/MM')) as theMonth 
    from dual) 

-- the actual query 
select card.* from card,cst 
    where (expiremonth = theMonth AND expireday > theDay) 
    or (expiremonth = 1+MOD(theMonth,12) AND expireday <= theDay); 
    --     ^^^^^^^^^^^^^^^^^^ 
    --   map [01 .. 12] to [02 .. 12, 01] (i.e.: next month) 

这会简单地选择所有的“伪日期”从明天开始到月底,以及任何一个之前(含)当天#下个月。

请参阅this example


对于一些有点更通用的,但可能不是将所有你的价值观TO_DATE更有效率,你可能会想尝试的是:

-- the calendar is the key part of the query (see below) 
with calendar as (
    select extract(month from sysdate + level) as theMonth, 
     extract(day from sysdate + level) as theDay 
    from DUAL connect by ROWNUM <= 8) 
--        ^
--    adjust to the right number of days you are looking for 
select card.* from card join calendar 
    on expiremonth = theMonth and expireDay = theDay 

这里的想法是简单地建立日历与所有即将到来的日子,然后加入您的数据表在该日历上。查看example here

相关问题