Sep 25 2007

Dynamic Dates Part IV: Yearly Date Ranges

Categories: Dynamic Dates,Universe Design Dave Rathbun @ 4:18 pm

Last Time On This Subject…

This is the fourth in my series about dynamic date objects. The first three included objects for daily, weekly, and then monthly ranges. I am going to complete my collection of Oracle-based dynamic date objects by providing yearly objects in this post.

Current Year

In the monthly post I showed how the Oracle trunc() function can be used to truncate (remove) everything except for the year and month. Here’s how to apply the same technique and get the first day of the year:

trunc(sysdate,'YYYY')

The formula shown above will “round off” the date to the year. Since the return value for this function has to be a date, Oracle returns the year + first month month + first day of the year. Short and simple. I have seen other formulas that convert a date to a string, extract the year with a substring operation, and then combine it back with ’01’ for the day and ’01’ for the month and then convert it back to a date. My advice? Use the trunc() function. 🙂

Readers that have followed this complete series will not be surprised with where I go to get the end of the current year. I could get the year from the current date (using string functions as outlined in the prior paragraph) and add in December and 31 for the day. Instead I will use this:

last_day(add_months(trunc(sysdate,'YYYY'), 11))

The advantage of this formula is that everything is based on date math. When I convert a date to character data and then use character functions there is a chance that the result value won’t be a valid date unless I do a lot of error checking. This way is fairly simple.

Why do I apply the trunc() function first? I do that to get to a constant starting point. Get to a known point and the offset (11 months) is always the same.

Last Year

As before I will be setting up objects for the prior year as well. This time instead of using the @Select() function I will do something slightly different. I will give you lots of options. 🙂

Date Formula
Start of Last Year V1 trunc(trunc(sysdate,’YYYY’)-1, ‘YYYY’)
Start of Last Year V2 add_months(trunc(sysdate,’YYYY’), -12)
Start of Last Year V3 trunc(@Select(‘Dynamic Dates\End of Last Year’), ‘YYYY’)
End of Last Year trunc(sysdate,’YYYY’)-1

What About Fiscal Calendar Years?

As I said in the prior post on monthly date ranges I would have to use a period calendar table or write custom database functions in order to create fiscal year objects. The standard Oracle database functions work only on a standard calendar. If you have a fiscal calendar and require dynamic yearly dates I strongly suggest that you look at creating a calendar table that supports your requirements. Note: I won’t be covering that process in this series of posts.

Summary

Over the past four posts I have built daily, weekly, monthly, and now yearly dynamic date objects. All of the prior posts in this series are conveniently linked below in case you missed one. What’s next? I realize that not everyone uses Oracle. Some of these formulas can easily be converted to other databases, and some are more challenging. I will try to show some of these same formulas in other databases. I don’t plan to try to do every date range for every database but will try to cover samples of each.

Remember that these objects are presented will not parse in Designer. They don’t reference a table and therefore will generate an error. As long as these objects are used with at least one “real” object on a query they will function perfectly fine.

Related Posts

Oracle functions used in this post

  • add_months() Returns an offset in months ahead or behind from the date given
  • last_day() Returns the last day of the month for the date given as an argument
  • trunc( , ‘YYYY) Returns a date value truncated to the first date of the year

Dynamic Dates With Oracle Functions

Date Formula
Today trunc(sysdate)
Yesterday trunc(sysdate-1)
Start of This Week next_day(trunc(sysdate-7), ‘Sunday’)
End of This Week next_day(case to_char(sysdate,’Day’) when ‘Saturday’ then trunc(sysdate-1) else trunc(sysdate) end, ‘Saturday’)
Start of Last Week @Select(‘Dynamic Dates\Start of This Week’) – 7
End of Last Week @Select(‘Dynamic Dates\End of This Week’) – 7
Start of This Month trunc(sysdate,’MM’)
End of This Month last_day(trunc(sysdate))
Start of Last Month add_months(@Select(‘Dynamic Dates\Start of This Month’) , -1)
End of Last Month add_months(@Select(‘Dynamic Dates\End of This Month’) , -1)
Start of This Year trunc(sysdate,’YYYY’)
End of This Year last_day(add_months(trunc(sysdate,’YYYY’),11))
Start of Last Year trunc(trunc(sysdate,’YYYY’)-1,’YYYY’)
End of Last Year trunc(sysdate,’YYYY’)-1

10 Responses to “Dynamic Dates Part IV: Yearly Date Ranges”

  1. Comment by Andreas

    Nice, for some time I have planned on conducting a workshop for consultants at my company on Date functions in Oracle, DB2, and Teradata together with design tips for smart time periods using universe and datamart design techinques.

  2. Comment by Dave Rathbun

    In researching an answer on BOB I found this link which includes many of the same function results for SQL Server so I decided to post it here:

    http://blog.sqlauthority.com/2008/08/29/sql-server-few-useful-datetime-functions-to-find-specific-dates/

    Now I don’t have to write my own blog post. 🙂 Hope this helps.

  3. Comment by Shiva

    Hey Dave,

    I’m working with BO from past 2 yrs. Have worked on 6.5, XIR2, XI3.0 and XI3.1(not extensively), Also on Voyager(pretty much). Have seen a lot of your post and found you really helpful.

    I’ve applied a logic to calculate Year to date.
    var1=(“1/1″+ formatdate(currentdate();”yyyy”))
    var2 = todate(var1;) will give you 1 january current year in date format.
    You can then use these variables to calculate YTD.

    The similar logic can be used to get the first date of a month. or
    =add_months(lastdateofthemonth(currentdate());-x) where x can be any number depending on the month you need.

  4. Comment by erika_yanina

    is there a way to achieve all that at Report Level isntead of Universe Level?

  5. Comment by Dave Rathbun

    Erika, it’s generally done at the universe because you have to create objects. You can create only variables on a report, and variables can be used for filters but not for query conditions. The universe is really the proper place for this sort of logic.

  6. Comment by GANESH

    hi dave can u pls explain the below written in sql

    SELECT DATEADD(ms,- 3,DATEADD(mm,0,DATEADD(mm,DATEDIFF(mm,0,GETDATE())+1,0)))
    ‘Last Day of Current Month’

    The above is to get last day of current month.

  7. Comment by cbslc

    Why is this so difficult in BOE? In an OLAP tool, I just make a date time dimension, tell it the start (for fiscal years …). Then I can use that wherever. But when I want a 13 month average for data on BOE. I have to do tons of gymnastics.

  8. Comment by ryan

    I agree with the above. Why is this so difficult. I’ve never worked anywhere that doesn’t want some date ranges. Cognos and analysis services both hve this functionality – including fiscal years, as drag and drop. BOE seems like its 11 years behind the industry.

  9. Comment by Chaitanya

    Hi Dave,

    I have a requirement to show the values for LAST 12 Months including Current Month. I am getting Fiscal Month/Year object from BEX without key in format of “MMM YYYY”. Currently data is available for 3 years and I just want to display the values against this MMM yyyy format including Current Month + Last 12 months.

    My report should look like this;

    Mar 2014 | 200
    Feb 2014 | 123
    Jan 2014 | 000
    .
    .
    .
    .
    .
    .
    .
    .
    .
    Mar 2013 | 123

    I referred many topics on forum but couldn’t succeed.
    Kindly help to get it done, I deadly need this.

    Thank you in advance.

  10. Comment by vinay

    Getting this Error [Microsoft][ODBC SQL Server Driver][SQL Server]Conversion failed when converting date and/or time from character string.

    When i tried below Code
    convert(varchar(8),DATEADD(ss, -1, DATEADD(month, DATEDIFF(month, 0, @Select(Mseg\User Date)), 0)),112)

    Please help me how to resolve it..

    Thanks
    vinay