Need to create Financial Year entries in Oracle 11g DB - sql

I need a financial year entries based on current or today's date AND time in Oracle11g DB.
Suppose if we consider today's date is 1ST April 2013, then i need the outputs as 01-APR-13 and 31-MAR-14.
Our requirement financial Year considered is from April (the current year) to March (following year).
Based on current datetime...the scenario of output depends on the current date-time which falls in the above said period or duration.
Another example: If we take today's datetime as 28th Dec 2012, then the output is needed as 01-APR-12 and 31-MAR-13.
Please help how to acheive the same in very short format using only SQL.
Consider the below table as
Create table venky (financialYearFrom DATE NOTNULL, financialYearTo DATE NOTNULL);

Something ugly:
SELECT to_date('1-APR-'||(to_char(sysdate,'yyyy')+
(case when to_char(sysdate,'mm')>3
then 0
else -1
end))) AS start_date ,
to_date('31-MAR-'||(to_char(sysdate,'yyyy')+
(case when to_char(sysdate,'mm')>3
then 1
else 0
end))) end_date
FROM dual;
If month > 3 then add a year to 31-MAR(end_of_period), else substract a year to 1-APR (start_of_period).
UPDATE: Something nicer:
select add_months(trunc(add_months(sysdate,-3),'yyyy'),3) as start_date ,
add_months(trunc(add_months(sysdate,-3),'yyyy'),15)-1 as end_date
from dual
Substracting 3 months will send you to the correct start year. Truncating to year and adding 3 months sends you to 1 APR. End_of period is 12 months ahead start minus one day.

create user define function for that here is example for SQL SERVER
find how to do it in oracle (both are same with minor diff in syntax)
CREATE FUNCTION [dbo].[getYear]
(
-- Add the parameters for the function here
#CurDate DATETIME
)
RETURNS VARCHAR(MAX)
AS
BEGIN
DECLARE #Y int;
SELECT #Y = CASE WHEN MONTH(#CurDate) <= 3 THEN YEAR(#CurDate) - 1 ELSE YEAR(#CurDate) END;
RETURN '01-APR-' + LTRIM(STR(#Y)) + ' and 31-MAR-' + LTRIM(STR(#Y+1));
END
and use it like this
Select dbo.GETYEAR(GETDATE());

Related

Combine and convert nvarchar month field + float year field to a single date field

I have a table in SQL Server 2012 with a month column stored as nvarchar(255):
"January", "February", "March"
And another column in this table with year stored separately as float
"2012","2013,"2014".
I do not have a day column so I want to create a combined month date column with the day starting as 1.
So for month and year fields January 2012. I want to show '2012-01-01'
How can I do such and add that into my current table?
I want to find the maximum row for a record in my table for each employee.
so for an [employee #], [month],[year]. what is latest record so for example below:
1. 102, Jan, 2019
2. 102, feb, 2019
I want to only see the second record which is the latest.
SQL Server has pretty flexible conversion to date. So, just convert the columns to a date:
select convert(date, month + ' ' + year)
You can get the maximum as:
select empid, max(convert(date, month + ' ' + year))
from t
group by empid;
If you really like, you can change the format for output purposes. I would advise you to stick with a date, though.
Note: This assumes that your internationalization settings are set to English -- which seems reasonable if you are storing month names in English.
Fix your design! The way you store data makes it really inefficient to interpret it. Here, I think the simplest option is datefromparts() and a 12-branches case expression.
Assuming that the (float) year is stored in column col_year and the (string) month is in col_month:
select t.*,
datefromparts(
cast(col_year as int),
case col_month
when 'January' then 1
when 'February' then 2
...
when 'December' then 12
end,
1
) as date_col
from mytable t

How to get last one month's data from a table based on current month and year?

I am facing some problem with the hive code.
My FROM TABLE is partitioned based on month, year and day. I came up with the following code to get the data I need. The logic is something like if the current mth is 01 then change the month to 12 and the year to yr - 1
else change month to mth - 1 and keep the year as is.
set hivevar:yr=2019;
set hivevar:mth=03;
set hivevar:dy=29;
SELECT * from
FROM table
WHERE
month = case when cast('${mth}' as int) = 01 then 12 else cast((cast('${mth}' as int) - 1) as string) end
AND year = case when cast('${mth}' as int) = 01 then cast((cast('${yr}' as int) - 1) as string) else '${yr}' end;
It is not working, my select * is coming empty. Please help.
desc table
From what i understand, you are trying to get data from the previous month given a date. If so, you can use inbuilt date functions to do it.
select *
from table
where concat_ws('-',year,month,day) >= add_months(date_add(concat_ws('-','${yr}','${mth}','${dy}'),1-'${dy}'), -1)
and concat_ws('-',year,month,day) < date_add(concat_ws('-','${yr}','${mth}','${dy}'),1-'${dy}')
The solution assumes year, month and day are of the format yyyy, MM and dd. If not, adjust them as needed
Also, you should consider storing date as a column even though you have it partitioned by year,month and day.

How to change day of date in SQL server and set last day of month if the day does not exist in the month

I tried using this
dateadd(month, 0, dateadd(day,(30-datepart(dd,'2015-02-28')),'2015-02-28'))
to get the required output and instead of getting '2015-02-28' i get '2015-03-02'. How is it possible to change day of date in SQL and set last day of month if the day does not exist in the month ?
====Update with sample data =============
Note: Goal is not to get the last day of the month
If i want to change the day to 30 and if it's a month which has only 28 days. it should be the end of the month date. If not date should be 30th.
Changing the day to 30th
If Feb it should be - '2015-02-28'
If march it should be - '2015-03-30'
If April it should be - '2015-04-30'
There exists a function for this if your sql server version is 2012 or higher:
SELECT EOMONTH('2015-02-15')
returns 2015-02-28
-- Replace Day portion of #OrigDate with #NewDay.
-- If the result would be beyond the end of the month, return the last day of the month
create function ReplaceDay ( #OrigDate date, #NewDay int )
returns date
as
begin
declare #NewDate date
-- Deal with extreme cases, in case someone passes #NewDay = 7777 or #NewDay = -7777
if #NewDay < 1
set #NewDay = 1
if #NewDay > 31
set #NewDay = 31
-- Subtract the DAY part of the original date from the new day.
-- Add that many days to the original date
-- Example: if the original date is 2018-02-08 and you want to replace 08 with 17, then add 17-08=9 days
set #NewDate = DateAdd ( d, #NewDay-Day(#OrigDate), #OrigDate )
-- Have we ended up in the next month?
-- If so subtract days so that we end up back in the original month.
-- The number of days to subtract is just the Day portion of the new date.
-- Example, if the result is 2018-03-02, then subtract 2 days
if Month(#NewDate)<>Month(#OrigDate)
set #NewDate = DateAdd ( d, -Day(#NewDate), #NewDate )
return #NewDate
end
go
select dbo.ReplaceDay ( '2017-02-08', 17 ) -- Returns 2017-02-17
select dbo.ReplaceDay ( '2017-02-08', 30 ) -- Returns 2017-02-28
for sql server 2012 or higher versions please check HoneyBadger's answer.
for older versions:
SELECT DATEADD(s,-1,DATEADD(mm, DATEDIFF(m,0,#mydate)+1,0))

Set a hardcoded day and month for a given year in TSQL

I am working on a small query and would like a little assistance formatting a date
Situation
I am accepting a payment date and based on that date I set the expiration date to 31st March of either this year or the next. So if the payment is made in January, the exp date is 31st March of the current year, if it's made in August, it's the 31st March of the next year.
This is my query.
BEGIN
IF DATEPART(MONTH,#paydate) BETWEEN 1 and 3
UPDATE usrBio
SET ExpDate=DATEPART(YEAR,GETDATE())+'-31'+'-03'
WHERE IDnum =#IDnum
ELSE IF
DATEPART(MONTH,#paydate) BETWEEN 4 and 12
UPDATE usrBio
SET ExpDate=DATEPART(YEAR,GETDATE()+1)+'-31'+'-03'
WHERE IDnum =#IDnum
END
The problem I am having is that I am unsure of how to set the month and day as instead of being concatenating to the year string, it's subtracting from the year date and my result is 1905-06-07 00:00:00.000 where I'm expecting 2017-31-03.
If 2012+, consider DateFromParts()
Example 1
Declare #PayDate date = '2017-08-31'
Select DateFromParts(Year(#PayDate)+IIF(Month(#PayDate)>3,1,0),3,31)
Returns
2018-03-31
----------------------
Example 2
Declare #PayDate date = '2017-03-31'
Select DateFromParts(Year(#PayDate)+IIF(Month(#PayDate)>3,1,0),3,31)
Returns
2017-03-31
**
Edit - For 2008
**
Select DateAdd(YEAR,case when Month(#PayDate)>3 then 1 else 0 end,str(Year(#PayDate),4)+'-03-31')
The problem is you trying year as number instead of string
DEMO
SELECT CAST( DATEPART(YEAR,GETDATE()+1)
AS varchar(5)) +'-03'+'-31'
And you can optimize your logic like this
UPDATE usrBio
SET ExpDate = CAST( CASE WHEN DATEPART(MONTH,#paydate) BETWEEN 1 and 3
THEN DATEPART(YEAR,GETDATE())
WHEN DATEPART(MONTH,#paydate) BETWEEN 4 and 12
THEN DATEPART(YEAR,GETDATE()+1)
END AS varchar(4)
) +'-03'+'-31'

SQL Server 2008 R2 - Creating a table of dates using a while statement. Looking for better options?

I'm trying to create a table of future dates. It will be easy to do with a while loop, but I know that isn't the most efficient way to do that in SQL. So I was hoping someone could share some ideas on how to do this in SQL set base manner.
Here is my code:
declare #count int, #dd date
set #count=0;
set #dd ='01/04/2013';
while (#count<24)
begin
select #dd=dateadd(week, 2,#dd);
set #count=#count+1;
select #dd
end
Thank you in advance...
Probably the best way to do this is with a fixed calendar table; go ahead and create a permanent table with all of the business rules you need for handling date logic.
As a workaround, you can do something like (assuming you have more than 24 columns in your database):
DECLARE #dd DATE
SET #dd = '01/04/2013';
SELECT TOP 24 DATEADD(week, 2*rn, #dd)
FROM (SELECT rn=(ROW_NUMBER() OVER (ORDER BY name)) -1
FROM sys.columns) c
We do something similar with our data warehouse. It's a two stage operation. One is to add new records with the primary key field only and the second is to update the other fields of the new records. The database engine is redbrick. redbrick syntax is similar to sql server syntax.
This is the insert query:
insert into period (date)
select
case when days_in_year((select max(date) from period))=365 -- current max year not leap year
and days_in_year(dateadd(day,1,(select max(date) from period)))=365 --new year not leap year
then dateadd(day,365,date)
else dateadd(day,366,date)end
from period
where date between
case when days_in_year(dateadd(day,1,(select max(date) from period)))=366 -- new year is leap year
or days_in_year((select max(date) from period))=366 -- current max year is leap year
then dateadd(day,-365, (select max(date) from period)) -- Dec 31 of year before current max year
else dateadd(day,-364, (select max(date) from period)) end --Jan 1 of current max year
and
case when days_in_year((select max(date) from period))=366 -- current max year is leap year
then dateadd(day,-1, (select max(date) from period))-- Dec 30 of current max year
else (select max(date) from period) end -- Dec 31 of current max year
and current_date > dateadd(month,-9,(select max(date) from period))
Note that days_in_year is a redbrick macro. In this case it's equivalent to a sql server user defined function. It's equivalent to this redbrick code
extract(dayofyear from date(concat(datename(year,%1),'-12-31')))
where %1 is the argument passed to the macro.