2016-11-29 56 views
2

Oracle有一個last_day()功能:甲骨文結束日期範圍內的月份值中

SELECT LAST_DAY(to_date('01/01/2016','DD/MM/YYYY')) from dual; 

結果:

31/01/2016 

我怎樣才能在一個日期範圍的使用EndOfMonths列表WHERE子句,目前我使用的是大串,這是不直觀,或者面向未來如:

SELECT * FROM Balances 
WHERE TheDate IN 
('31/Jan/2016','29/Feb/2016', '31/Mar/2016','30/Apr/2016', '31/May/2016','30/Jun/2016', '31/Jul/2016','31/Aug/2016', 
'30/Sep/2016', '31/Oct/2016','30/Nov/2016') 

我寧願我們e插入開始日期和結束日期的功能,非常感謝任何想法。

回答

1

嘗試是這樣的生成本月範圍的最後一天:

SELECT LAST_DAY(add_months(to_date('01/01/2016','DD/MM/YYYY'), level)) 
from dual 
CONNECT BY LEVEL <= 10 

更改10#幾個月裏,你所需要的。這假設「TheDate」是一個適當的oracle DATE類型。如果需要,可以使用to_char進行換行來格式化爲字符串。

隨着@JeremyThompsons MONTHS_BETWEEN建議:

SELECT LAST_DAY(add_months(to_date('01-01-1991','DD/MM/YYYY'), level)) 
from dual 
CONNECT BY LEVEL <= 
(SELECT MONTHS_BETWEEN 
    (TO_DATE('02-02-1999','MM-DD-YYYY'), 
    TO_DATE('01-01-1991','MM-DD-YYYY')) "Months" 
    FROM dual); 

與@mathguys功能順序建議的最終查詢:

SELECT * FROM Balances b 
WHERE TheDate IN 
(SELECT add_months(LAST_DAY(to_date('28/Feb/2015','DD-MM-YYYY')), level) 
from dual 
CONNECT BY LEVEL <= 
(SELECT MONTHS_BETWEEN 
    (TO_DATE('30/Nov/2016','DD-MM-YYYY'), 
    TO_DATE('28/Feb/2015','DD-MM-YYYY')) "Months" 
    FROM dual)); 

還有一@mathguys的優化,不需要標量子查詢:

SELECT * FROM Balances b 
WHERE TheDate IN 
(SELECT add_months(LAST_DAY(to_date('28/Feb/2015','DD-MM-YYYY')),level) 
from dual 
CONNECT BY LEVEL <= MONTHS_BETWEEN 
    (TO_DATE('30/Nov/2016','DD-MM-YYYY'), 
    TO_DATE('28/Feb/2015','DD-MM-YYYY'))); 
+0

所以只是MONTHS_BETWEEN來完成它,我將修改你的答案,謝謝 –

+1

'add_months'可以在第一個參數的月末使用,在這種情況下,它只返回月末。然後你可以將呼叫保存到'last_day()'。嘗試例如'select_add_months(last_day(sysdate),level)來自雙連接級別<= 12;'並根據需要進行調整。 – mathguy

+0

進一步增強,如果輸入月末日期,可以消除'LAST_DAY',爲什麼我提到這是由於@mathguy的建議,並且它並不直接顯而易見,Oracle的ADD_MONTHS功能非常智能*並且在引擎蓋下進行了優化*,你可以使用2月28日或29日,4月30日但不是3月30日。偉大的團隊合作伙伴! –

0

你可以創建一個如下所示的函數retu氡月結束所有月份:

create or replace function getEndOfMonths return varchar2 as 
    cnt number; 
    current_year varchar2(5); 
    end_of_months varchar2(180) := ''; 
    end_of_month varchar2(13); 
begin 
    select to_char(sysdate,'YYYY') into current_year from dual; 
    for cnt in 1..12 loop 
     SELECT LAST_DAY(to_date('01/'||cnt||'/'||current_year,'DD/MM/YYYY')) into end_of_month from dual; 
     end_of_months := end_of_months||','||end_of_month; 
    end loop; 
    return substr(end_of_months,2); 
end; 
/

更新: 下面是根據每月範圍:

create or replace function getEndOfMonths(start_month number, end_month number) return varchar2 as 
    cnt number; 
    current_year varchar2(5); 
    end_of_months varchar2(180) := ''; 
    end_of_month varchar2(13); 
begin 
    select to_char(sysdate,'YYYY') into current_year from dual; 
    for cnt in start_month..end_month loop 
     SELECT LAST_DAY(to_date('01/'||cnt||'/'||current_year,'DD/MM/YYYY')) into end_of_month from dual; 
     end_of_months := end_of_months||','||end_of_month; 
    end loop; 
    return substr(end_of_months,2); 
end; 
/
+0

這不會起作用。這是一個大字符串,而不是一個IN列表。 – OldProgrammer