2014-09-22 51 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

相關問題