Working out a date from a single month number SQL - sql

Got 2 parameters #yr and #period, #period is just the month number so July would equal 7 for example.
In my stored procedure table I've got a column called Date which is just a standard datetime field. I need a where clause to work out all dates greater than the current period minus 1 year so if #period = 7 and #yr = 2012 I want the where clause to return all dates greater than '01-07-2011' (UK date format) how can I achieve this with just the 2 numbers from #period and #yr.
WHERE <br>
Date >= '01-07-2011'

You could
Date >= dateadd(month, #period-1, dateadd(year, #yr-1900, 0))

where year(date)>year(getdate()-1) and month(date)>#period

If you want the expression sargable, convert it to datetime:
declare #year int = 2012
declare #month int = 7
select
...
where [Date] >= convert(datetime, convert(varchar(4), #year)
+ right('0' + convert (varchar(2), #month), 2)
+ '01')
After seeing Alex K.'s answer, you might even do this:
dateadd(month, #month - 1 + (#year-1900) * 12, 0)

For the best performance you should do something like this:
declare #yr int = 2012
declare #period int = 7
select ...
from ....
WHERE date >= dateadd(month, (#yr - 1901) * 12 + #period - 1, 0)

We can do it in may ways
try it
DECLARE #a VARCHAR(20),
#b VARCHAR(10),
#c varchar(4)
SET #b='may' /*pass your stored proc value */
SET #c='2011'
SET #a='01'+#b+#c
SET DATEFORMAT YDM
SELECT CAST(#a AS DATE)
FOR uk formate
SELECT CONVERT(char,CAST(#a AS DATE),103)

Just t make sure you compare against an entire date, one solution I'd offer is:
Select *
from TheTable
where date> DateAdd(Year,-1, convert(datetime, '01/'+convert(varchar,#period)+'/' + convert(varchar,#yr)))
To account for regional format differences in SQL Server 2012:
Select *
from TheTable
where date> DateAdd(Year,-1, DateFromParts(#year,#period,1))
For pre-2012:
Select *
from TheTable
Where Date > DateAdd(day, 0, DateAdd(month, #period-1, DateAdd(year, (#yr-1900)-1,0)))
The #yr-1900 is maintained to illustrate the computation of the base date offset from 1900, then subtracting 1 for the one-year-off date computation

Related

How to get number of days in a month in SQL Server

Is there a way to get the number of days in a month in SQL Server, if we input the month number or month name, or even a date?
You can use:
select day(eomonth ('2018-02-01')) as NoOfDays
and the result will be:
NoOfDays
-----------
28
If you have a date, then simply do:
select day(eomonth(date))
If you have a month number, then:
select day(eomonth(datefromparts(2020, month_number, 1)))
If you have a date and are on 2012 or later :
SELECT day(eomonth(yourdate))
Month name / number is automatically prone to an error when dealing with February - do you consider it 28 or 29, which year are you referring to when making that calculation etc.
In case you are using sql-server 2008 or earlier:
Date as input
DECLARE #date DATETIME = getdate()
SELECT day(dateadd(m, datediff(m, -1, #date), -1))
Month and year as input
DECLARE #year INT = 2018
DECLARE #month INT = 2
SELECT day(dateadd(m, #month + datediff(m, 0, cast(#year as char(4))), -1))
try using
SELECT day(eomonth(yourdate))
for pre 2012 where eomonth() is not available
if you have a date
select day(dateadd(month, datediff(month, 0, #date) + 1, -1))
if you have the year & month
declare #year int = 2018,
#month int = 8
select dateadd(month, #month, dateadd(year, #year - 1900, -1))

Compare the date if the columns (day, month and year) are stored separately in SQL Server

I have 3 columns Day, Month and Year of type INT that are totally separate. What I need is to pass a date (format: yyyy-mm-dd) into a WHERE clause to check if this following date is matched or not. What would be the best approach to handle this issue?
In 2012 it would be DateFromParts(Year,Month,Day), but you have tagged 2008 which means we have to fall back to the older tricks.
dateadd(mm, (#YourYearValue - 1900) * 12 + #YourMonthValue- 1 , #YourDayValue - 1)
Put your 3 ints into that (via columns from a join or parameters as appropriate) and you have a date returned you can work with.
SQL Fiddle : http://www.sqlfiddle.com/#!18/9eecb/19988
For SQL Server 2008
declare #Day int = 29, #Month int = 5, #Year int = 2018
select t.*
from [table] t
where t.[Date] = cast(cast(#Year as char(4))+ '-' + cast(#Month as char(2)) + '-' + cast(#Day as char(2)) as date)
Only for 2012 and later use DATEFROMPARTS:
where t.[Date] = DATEFROMPARTS(#Year, #Month, #Day)
Maybe this solution:
where cast(cast(#yyyy as varchar(4))+'-'+cast(#mm as varchar(2))+'-'+cast(#dd as
varchar(2)) as date) ...
and replace #yyyy,#mm,#dd with your fields
I would suggest the following, Instead of making a date using separated values we can take part from the complete date using SQL functions and compare with accordingly, which I think the best way of comparison
DECLARE #Day INT=29, #Month INT=05, #Year INT = 2018,
#Date DATE = '2018-05-29'
SELECT * FROM yourTable
WHERE YEAR(#Date) = #Year
AND MONTH(#Date) = #Month
AND DAY(#Date) = #Day

Convert Julian Date to YYYY-MM-DD

I have searched far and wide, but I can't seem find a way to convert julian to yyyy-mm-dd.
Here is the format of my julian:
The Julian format consists of the year, the first two digits, and the day within the year, the last three digits.
For example, 95076 is March 17, 1995. The 95 indicates the year and the
076 indicates it is the 76th day of the year.
15260
I have tried this but it isn't working:
dateadd(d,(convert(int,LAST_CHANGED_DATE) % 1000)-1, convert(date,(convert(varchar,convert(int,LAST_CHANGED_DATE) /1000 + 1900) + '/1/1'))) as GrgDate
You can select each part of the date using datepart()
SELECT DATEPART(yy, 95076), DATEPART(dy, 95076)
+++EDIT: I misunderstood something. Here's my correction: +++++
SELECT DATEADD(day, CAST(RIGHT('95076',3) AS int) – 1, CONVERT(datetime,LEFT('95076',2) + '0101', 112))
Edit: leaving this answer for Oracle and MySQL users
This will not work in T-SQL.
Use this:
MAKEDATE(1900 + d / 1000, d % 1000)
For example:
SELECT MAKEDATE(1900 + 95076 / 1000, 95076 % 1000)
This returns March, 17 1995 00:00:00.
SQLFiddle
I concatenated 20 to my JD and then ran
DATEADD(YEAR, LAST_CHANGE_DATE / 1000 - 1900, LAST_CHANGE_DATE % 1000 - 1)
this got me the result. Thank you!!!
FOR SQL Users
DECLARE #jdate VARCHAR(10)
SET #jdate = 117338
SELECT dateadd(dd, (#jdate - ((#jdate/1000) * 1000)) - 1, dateadd(yy, #jdate/1000, 0))
This will definitely work in all case.
DECLARE #date int
SET #date = 21319
SELECT DATEADD(dd, RIGHT(#date,LEN(#date)-3)-1, DATEADD(yy,LEFT(#date,1)*100 +RIGHT(LEFT(#date,3),2),'1 Jan 1900'))
You need to specify 1 or 0 for century in first character. For example, SET #date = 21319 should be prefixed with 1 or 0. Below is an example that will work with all y2k use cases.
DECLARE #jdate INT
SET #jdate = 119150
SELECT DATEADD(dd, (#jdate - ((#jdate/1000) * 1000)) - 1, DATEADD(yy, #jdate/1000, 0))
Declare #Julian varchar(7)
Declare #date date
Set #Julian = 2020277
Set #Date = Dateadd(day,+ Cast(right(#Julian,3) as int)-1, Cast(left(#Julian,4) + '0101' as Date))
Select #Date
Standard SQL is simple (you can do similar for 2 digit year YYMMDD)
Declare #julDate int = 2020275
Select
DateAdd
(
day
, Right(#julDate,3)-1
, Cast((Left(#julDate,4)+'-01-01') as smalldatetime)
)
Try this out:
DECLARE #jdate int
SET #jdate = 21243
select dateadd(dd, (#jdate - ((#jdate/1000) * 1000)) - 1, dateadd(yy, #jdate/1000+100, 0))

Date calculation in variable

I'm doing my best to set a date variable so I can compare it later. I would like something that basically says:
If the current day-of-month is less than 11, then date is 10th of LAST month
If the current day-of-month is greater-than-or-equal-to 11, then date is 10th of THIS month
Date is 11/6/2012 expected output:
#PODate = 10/10/2012
Date is 11/16/2012 expected output:
#PODate = 11/10/2012
Currently all I have is this:
DECLARE #PODate as DATETIME
Set #PODate = Convert(varchar(8),GetDate(),1)
Any tips or help would be greatly appreciated. Thank you!!
Trying to keep it as straightforward as possible:
declare #PODate datetime
select #PODate = DATEADD(month,
DATEDIFF(month,'20010110',CURRENT_TIMESTAMP) +
CASE WHEN DATEPART(day,CURRENT_TIMESTAMP) <= 10 THEN -1 ELSE 0 END,
'20010110')
The surrounding DATEADD/DATEDIFF pair are being used to normalize the date to the 10th of the current month. We then use a small CASE expression to subtract a month if the day is less than or equal to the 10th.
Whatever solution you pick, please try to avoid ones that do it as string manipulation. The usual cause of datetime related bugs in SQL is when people treat dates as strings. Keeping the data types appropriately is usually the best way to prevent these issues.
There are, admittedly, 2 strings in my solution, but these are fixed constant strings (all that matters is that they're both for the same year and month, and the second one is for the 10th of the month) and are in an unambiguous format.
Try this: SQL Fiddle
DECLARE
#PODate as DATETIME,
#LastMonth as DateTime,
#strDate as Varchar(50)
set #PODate = '11/16/2012'
set #LastMonth = DATEADD(MONTH, -1, #PODate)
if(DAY(#PODate) < 11)
SET #strDate = CAST(MONTH(#LastMonth) AS VARCHAR)+'/10/'+CAST(YEAR(#LastMonth) AS VARCHAR)
else
SET #strDate = CAST(MONTH(#PODate) AS VARCHAR)+'/10/'+CAST(YEAR(#PODate) AS VARCHAR)
Select CAST(#strDate AS DateTime)
DECLARE #PODate date = '20121116'
SELECT CASE WHEN DATEPART(day, #PODate) < 11 THEN DATEADD(mm, DATEPART(mm, GETDATE()) - DATEPART(mm, #PODate) - 1, DATEADD(day, 10 - DATEPART(day, #PODate), #PODate))
ELSE DATEADD(mm, DATEPART(mm, GETDATE()) - DATEPART(mm, #PODate), DATEADD(day, 10 - DATEPART(day, #PODate), #PODate)) END
Demo on SQLFiddle
DECLARE #currDate DATE = dbo.GetDate()
DECLARE #day INT = day(#currDate)
DECLARE #month INT
DECLARE #year INT
DECLARE #PODate DATE
IF( #day >= 11)
BEGIN
SET #month = month(#currDate)
SET #year = year(#currDate)
END
ELSE BEGIN
SET #month = month(dateadd(m,-1,#currDate))
SET #year = year(dateadd(m,-1,#currDate))
END
SET #PODate = convert(DATE,'10-' + convert(VARCHAR,#month) + '-' + convert(VARCHAR,#year))
PRINT #PODate
if #currDate = '11-jan-2013' , #PODate will be '10-jan-2013', and if #currDate = '07-jan-2013' , #PODate will be '10-Dec-2012'

How to determine the number of days in a month in SQL Server?

I need to determine the number of days in a month for a given date in SQL Server.
Is there a built-in function? If not, what should I use as the user-defined function?
In SQL Server 2012 you can use EOMONTH (Transact-SQL) to get the last day of the month and then you can use DAY (Transact-SQL) to get the number of days in the month.
DECLARE #ADate DATETIME
SET #ADate = GETDATE()
SELECT DAY(EOMONTH(#ADate)) AS DaysInMonth
You can use the following with the first day of the specified month:
datediff(day, #date, dateadd(month, 1, #date))
To make it work for every date:
datediff(day, dateadd(day, 1-day(#date), #date),
dateadd(month, 1, dateadd(day, 1-day(#date), #date)))
Most elegant solution: works for any #DATE
DAY(DATEADD(DD,-1,DATEADD(MM,DATEDIFF(MM,-1,#DATE),0)))
Throw it in a function or just use it inline. This answers the original question without all the extra junk in the other answers.
examples for dates from other answers:
SELECT DAY(DATEADD(DD,-1,DATEADD(MM,DATEDIFF(MM,-1,'1/31/2009'),0))) Returns 31
SELECT DAY(DATEADD(DD,-1,DATEADD(MM,DATEDIFF(MM,-1,'2404-feb-15'),0))) Returns 29
SELECT DAY(DATEADD(DD,-1,DATEADD(MM,DATEDIFF(MM,-1,'2011-12-22'),0))) Returns 31
--Last Day of Previous Month
SELECT DATEPART(day, DATEADD(s,-1,DATEADD(mm, DATEDIFF(m,0,GETDATE()),0)))
--Last Day of Current Month
SELECT DATEPART(day, DATEADD(s,-1,DATEADD(mm, DATEDIFF(m,0,GETDATE())+1,0)))
--Last Day of Next Month
SELECT DATEPART(day, DATEADD(s,-1,DATEADD(mm, DATEDIFF(m,0,GETDATE())+2,0)))
Personally though, I would make a UDF for it if there is not a built in function...
I would suggest:
SELECT DAY(EOMONTH(GETDATE()))
This code gets you the number of days in current month:
SELECT datediff(dd,getdate(),dateadd(mm,1,getdate())) as datas
Change getdate() to the date you need to count days for.
--- sql server below 2012---
select day( dateadd(day,-1,dateadd(month, 1, convert(date,'2019-03-01'))))
-- this for sql server 2012--
select day(EOMONTH(getdate()))
Solution 1: Find the number of days in whatever month we're currently in
DECLARE #dt datetime
SET #dt = getdate()
SELECT #dt AS [DateTime],
DAY(DATEADD(mm, DATEDIFF(mm, -1, #dt), -1)) AS [Days in Month]
Solution 2: Find the number of days in a given month-year combo
DECLARE #y int, #m int
SET #y = 2012
SET #m = 2
SELECT #y AS [Year],
#m AS [Month],
DATEDIFF(DAY,
DATEADD(DAY, 0, DATEADD(m, ((#y - 1900) * 12) + #m - 1, 0)),
DATEADD(DAY, 0, DATEADD(m, ((#y - 1900) * 12) + #m, 0))
) AS [Days in Month]
You do need to add a function, but it's a simple one. I use this:
CREATE FUNCTION [dbo].[ufn_GetDaysInMonth] ( #pDate DATETIME )
RETURNS INT
AS
BEGIN
SET #pDate = CONVERT(VARCHAR(10), #pDate, 101)
SET #pDate = #pDate - DAY(#pDate) + 1
RETURN DATEDIFF(DD, #pDate, DATEADD(MM, 1, #pDate))
END
GO
SELECT Datediff(day,
(Convert(DateTime,Convert(varchar(2),Month(getdate()))+'/01/'+Convert(varchar(4),Year(getdate())))),
(Convert(DateTime,Convert(varchar(2),Month(getdate())+1)+'/01/'+Convert(varchar(4),Year(getdate()))))) as [No.of Days in a Month]
select datediff(day,
dateadd(day, 0, dateadd(month, ((2013 - 1900) * 12) + 3 - 1, 0)),
dateadd(day, 0, dateadd(month, ((2013 - 1900) * 12) + 3, 0))
)
Nice Simple and does not require creating any functions Work Fine
You need to create a function, but it is for your own convenience. It works perfect and I never encountered any faulty computations using this function.
CREATE FUNCTION [dbo].[get_days](#date datetime)
RETURNS int
AS
BEGIN
SET #date = DATEADD(MONTH, 1, #date)
DECLARE #result int = (select DAY(DATEADD(DAY, -DAY(#date), #date)))
RETURN #result
END
How it works: subtracting the date's day number from the date itself gives you the last day of previous month. So, you need to add one month to the given date, subtract the day number and get the day component of the result.
select add_months(trunc(sysdate,'MM'),1) - trunc(sysdate,'MM') from dual;
I upvoted Mehrdad, but this works as well. :)
CREATE function dbo.IsLeapYear
(
#TestYear int
)
RETURNS bit
AS
BEGIN
declare #Result bit
set #Result =
cast(
case when ((#TestYear % 4 = 0) and (#testYear % 100 != 0)) or (#TestYear % 400 = 0)
then 1
else 0
end
as bit )
return #Result
END
GO
CREATE FUNCTION dbo.GetDaysInMonth
(
#TestDT datetime
)
RETURNS INT
AS
BEGIN
DECLARE #Result int
DECLARE #MonthNo int
Set #MonthNo = datepart(m,#TestDT)
Set #Result =
case #MonthNo
when 1 then 31
when 2 then
case
when dbo.IsLeapYear(datepart(yyyy,#TestDT)) = 0
then 28
else 29
end
when 3 then 31
when 4 then 30
when 5 then 31
when 6 then 30
when 7 then 31
when 8 then 31
when 9 then 30
when 10 then 31
when 11 then 30
when 12 then 31
end
RETURN #Result
END
GO
To Test
declare #testDT datetime;
set #testDT = '2404-feb-15';
select dbo.GetDaysInMonth(#testDT)
here's another one...
Select Day(DateAdd(day, -Day(DateAdd(month, 1, getdate())),
DateAdd(month, 1, getdate())))
I know this question is old but I thought I would share what I'm using.
DECLARE #date date = '2011-12-22'
/* FindFirstDayOfMonth - Find the first date of any month */
-- Replace the day part with -01
DECLARE #firstDayOfMonth date = CAST( CAST(YEAR(#date) AS varchar(4)) + '-' +
CAST(MONTH(#date) AS varchar(2)) + '-01' AS date)
SELECT #firstDayOfMonth
and
DECLARE #date date = '2011-12-22'
/* FindLastDayOfMonth - Find what is the last day of a month - Leap year is handled by DATEADD */
-- Get the first day of next month and remove a day from it using DATEADD
DECLARE #lastDayOfMonth date = CAST( DATEADD(dd, -1, DATEADD(mm, 1, FindFirstDayOfMonth(#date))) AS date)
SELECT #lastDayOfMonth
Those could be combine to create a single function to retrieve the number of days in a month if needed.
SELECT DAY(SUBDATE(ADDDATE(CONCAT(YEAR(NOW()), '-', MONTH(NOW()), '-1'), INTERVAL 1 MONTH), INTERVAL 1 DAY))
Nice 'n' Simple and does not require creating any functions
Mehrdad Afshari reply is most accurate one, apart from usual this answer is based on formal mathematical approach given by Curtis McEnroe in his blog https://cmcenroe.me/2014/12/05/days-in-month-formula.html
DECLARE #date DATE= '2015-02-01'
DECLARE #monthNumber TINYINT
DECLARE #dayCount TINYINT
SET #monthNumber = DATEPART(MONTH,#date )
SET #dayCount = 28 + (#monthNumber + floor(#monthNumber/8)) % 2 + 2 % #monthNumber + 2 * floor(1/#monthNumber)
SELECT #dayCount + CASE WHEN #dayCount = 28 AND DATEPART(YEAR,#date)%4 =0 THEN 1 ELSE 0 END -- leap year adjustment
To get the no. of days in a month we can directly use Day() available in SQL.
Follow the link posted at the end of my answer for SQL Server 2005 / 2008.
The following example and the result are from SQL 2012
alter function dbo.[daysinm]
(
#dates nvarchar(12)
)
returns int
as
begin
Declare #dates2 nvarchar(12)
Declare #days int
begin
select #dates2 = (select DAY(EOMONTH(convert(datetime,#dates,103))))
set #days = convert(int,#dates2)
end
return #days
end
--select dbo.daysinm('08/12/2016')
Result in SQL Server SSMS
(no column name)
1 31
Process:
When EOMONTH is used, whichever the date format we use it is converted into DateTime format of SQL-server. Then the date output of EOMONTH() will be 2016-12-31 having 2016 as Year, 12 as Month and 31 as Days.
This output when passed into Day() it gives you the total days count in the month.
If we want to get the instant result for checking we can directly run the below code,
select DAY(EOMONTH(convert(datetime,'08/12/2016',103)))
or
select DAY(EOMONTH(convert(datetime,getdate(),103)))
for reference to work in SQL Server 2005/2008/2012, please follow the following external link ...
Find No. of Days in a Month in SQL
DECLARE #date DATETIME = GETDATE(); --or '12/1/2018' (month/day/year)
SELECT DAY(EOMONTH ( #date )) AS 'This Month';
SELECT DAY(EOMONTH ( #date, 1 )) AS 'Next Month';
result:
This Month
31
Next Month
30
DECLARE #m int
SET #m = 2
SELECT
#m AS [Month],
DATEDIFF(DAY,
DATEADD(DAY, 0, DATEADD(m, +#m -1, 0)),
DATEADD(DAY, 0, DATEADD(m,+ #m, 0))
) AS [Days in Month]
RETURN day(dateadd(month, 12 * #year + #month - 22800, -1))
select day(dateadd(month, 12 * year(date) + month(date) - 22800, -1))
A cleaner way of implementing this is using the datefromparts function to construct the first day of the month, and calculate the days from there.
CREATE FUNCTION [dbo].[fn_DaysInMonth]
(
#year INT,
#month INT
)
RETURNS INT
AS
BEGIN
IF #month < 1 OR #month > 12 RETURN NULL;
IF #year < 1753 OR #year > 9998 RETURN NULL;
DECLARE #firstDay DATE = datefromparts(#year, #month, 1);
DECLARE #lastDay DATE = dateadd(month, 1, #firstDay);
RETURN datediff(day, #firstDay, #lastDay);
END
GO
Similarily, you can calculate the days in a year:
CREATE FUNCTION [dbo].[fn_DaysInYear]
(
#year INT
)
RETURNS INT
AS
BEGIN
IF #year < 1753 OR #year > 9998 RETURN NULL;
DECLARE #firstDay DATE = datefromparts(#year, 1, 1);
DECLARE #lastDay DATE = dateadd(year, 1, #firstDay);
RETURN datediff(day, #firstDay, #lastDay);
END
GO
use SQL Server EOMONTH Function nested with day to get last day of month
select Day(EOMONTH('2020-02-1')) -- Leap Year returns 29
select Day(EOMONTH('2021-02-1')) -- returns 28
select Day(EOMONTH('2021-03-1')) -- returns 31
For any date
select DateDiff(Day,#date,DateAdd(month,1,#date))
select first_day=dateadd(dd,-1*datepart(dd,getdate())+1,getdate()),
last_day=dateadd(dd,-1*datepart(dd,dateadd(mm,1,getdate())),dateadd(mm,1,getdate())),
no_of_days = 1+datediff(dd,dateadd(dd,-1*datepart(dd,getdate())+1,getdate()),dateadd(dd,-1*datepart(dd,dateadd(mm,1,getdate())),dateadd(mm,1,getdate())))
replace any date with getdate to get the no of months in that particular date
DECLARE #Month INT=2,
#Year INT=1989
DECLARE #date DateTime=null
SET #date=CAST(CAST(#Year AS nvarchar) + '-' + CAST(#Month AS nvarchar) + '-' + '1' AS DATETIME);
DECLARE #noofDays TINYINT
DECLARE #CountForDate TINYINT
SET #noofDays = DATEPART(MONTH,#date )
SET #CountForDate = 28 + (#noofDays + floor(#noofDays/8)) % 2 + 2 % #noofDays + 2 * floor(1/#noofDays)
SET #noofDays= #CountForDate + CASE WHEN #CountForDate = 28 AND DATEPART(YEAR,#date)%4 =0 THEN 1 ELSE 0 END
PRINT #noofDays
DECLARE #date nvarchar(20)
SET #date ='2012-02-09 00:00:00'
SELECT DATEDIFF(day,cast(replace(cast(YEAR(#date) as char)+'-'+cast(MONTH(#date) as char)+'-01',' ','')+' 00:00:00' as datetime),dateadd(month,1,cast(replace(cast(YEAR(#date) as char)+'-'+cast(MONTH(#date) as char)+'-01',' ','')+' 00:00:00' as datetime)))
simple query in SQLServer2012 :
select day(('20-05-1951 22:00:00'))
i tested for many dates and it return always a correct result