I am trying to create a query that yields Year, Iso week and sum of amount for that year and week.
My problem is that the way I am doing it returns the amount for the first days of 2021 as being from week 53 when it actually should of course be a part of week 53 of the year 2020.
Here is my query:
SELECT
datepart(year, [MyDate]) AS [Year],
datepart(iso_week,[MyDate]) AS WeekNumber,
sum([Amount]) AS TotalAmount
FROM [Temp].[dbo].[MyTable]
GROUP BY datepart(year, [MyDate]), datepart(iso_week,[MyDate])
ORDER BY datepart(year, [MyDate]), datepart(iso_week,[MyDate])
How can this be fixed?
Sadly, SQL Server offers iso_week as an argument to datepart(), but not iso_year. Some perusing on the web suggests this code:
SELECT v.iso_year, v.iso_week,
sum([Amount]) AS TotalAmount
FROM [Temp].[dbo].[MyTable] t CROSS APPLY
(VALUES (YEAR(DATEADD(day, 26 - DATEPART(isoww, DATEFROMPARTS(YEAR(t.mydate), 1, 1)), DATEFROMPARTS(YEAR(t.mydate), 1, 1))),
datepart(iso_week, t.[MyDate])
)
) v(iso_year, iso_week)
GROUP BY iso_year, iso_week
ORDER BY iso_year, iso_week
I found a solution by doing this:
SELECT
dbo.GetIsoYear(MyDate) AS [Year],
datepart(iso_week,MyDate) AS WeekNumber,
sum(Amount) AS 'TotalAmount'
FROM MyTable
GROUP BY dbo.GetIsoYear(MyDate), datepart(iso_week,MyDate)
ORDER BY dbo.GetIsoYear(MyDate), datepart(iso_week,MyDate)
and here is the function I am using:
ALTER FUNCTION [dbo].[GetIsoYear](#Date datetime)
RETURNS int
AS
BEGIN
DECLARE #ResultVar int
DECLARE #IsoWeek int
DECLARE #Month int
SELECT #IsoWeek = DATEPART(ISO_WEEK,#Date)
SELECT #Month = DATEPART(MONTH,#Date)
IF #IsoWeek = 53 AND #Month = 1
SET #ResultVar = YEAR(#Date) - 1
ELSE
SET #ResultVar = YEAR(#Date)
RETURN #ResultVar
END
I do not know if using a function here has performance issues but I would think that it should run rather fast.
How can I get month diff as integer based on month names in string (January, February, March, etc.) ?
For example, I have a variable declare #month varchar(20) = 'May';
and Select DATEDIFF(month, month(getdate()), #month) should be 7 (the
difference between October and May).
In SQL Server, you would use datediff():
select datediff(month, '2010-01-15', '2011-02-28')
This counts the number of month boundaries between two dates. That sounds like a reasonable interpretation of your question.
Declare #M1 varchar(25) = 'October'
Declare #M2 varchar(25) = 'May'
Select DateDiff(MONTH,#M1+' 01 1980',#M2+' 01 1980')
+case when DateDiff(MONTH,#M1+' 01 1980',#M2+' 01 1980')<0 then 12 else 0 end
Returns 7
DECLARE #M1 as varchar(20) = 'October';
DECLARE #M2 as varchar(20) = 'May';
SELECT ABS(datediff(mm,
convert(datetime, #M1 + ' 1 2012 11:01AM', 100),
convert(datetime, #M2 + ' 1 2012 11:01AM', 100)
)
);
this doesn't allow for years ,which you didn't mention previously
Assuming input1,input2, there you go:
declare #input1 nvarchar(max)='October'
declare #input2 nvarchar(max)='May'
select
case
when DATEPART(MM,#input1+' 01 2011')>DATEPART(MM,#input2+' 01 2011')
then 12
else 0
end-DATEPART(MM,#input1+' 01 2011')+DATEPART(MM,#input2+' 01 2011')
try this
select DATEPART(MM,'march 01 2011') - DATEPART(MM,'january 01 2011')
Not sure what you are trying to do, but something like this might work:
select MONTH(STR_TO_DATE('October', '%M')) - MONTH(STR_TO_DATE('May', '%M')) -- returns 5
Try this
DECLARE #Date1 VARCHAR(10),#Date2 VARCHAR(10)
SET #Date1='January'
SET #Date2='DECEMBER'
;WITH CTE
AS
(
SELECT Number AS EnglishMOnthNumber,
DATENAME(MONTH,DATEADD(MONTH,NUMBER-DATEPART(MONTH,GETDATE()),GETDATE())) AS EnglishMOnth
FROM master.dbo.spt_values
WHERE NUmber Between 1 and 12
AND type='P'
)
SELECT MAX(CASE WHEN EnglishMOnth=#Date2 THEN EnglishMOnthNumber END)
- MAX( CASE WHEN EnglishMOnth=#Date1 THEN EnglishMOnthNumber END ) AS DiffInMonths
FROM CTE
I would get the difference between the required month (in your case May) and current month, If the difference is less than 0 then I would add the number of months (12) to it to get the calculation else nothing would be added. This is just one more way better answers above
declare #RequiredMonth varchar(25) = 'February';
declare #difference as int;
set #difference = MONTH(cast(#RequiredMonth+'1 2016' as datetime)) - MONTH(getdate())
select case when #difference >= 0 then #difference else #difference + 12 end
You could use something like this :
DECLARE
#month varchar(20) = 'May'
SELECT DATEDIFF(MONTH, GETDATE(), EndDate)
FROM (SELECT CAST(#month + CAST( YEAR(GETDATE()) + 1 AS VARCHAR(4)) AS DATE) EndDate) D
What's the most efficient way to calculate the first day of the current (Australian) Financial Year?
The Australian FY begins on 01-July.
E.g.
SELECT dbo.FinancialYearStart('30-Jun-2011') returns 01-Jul-2010.
SELECT dbo.FinancialYearStart('01-Jul-2011') returns 01-Jul-2011.
SELECT dbo.FinancialYearStart('02-Jul-2011') returns 01-Jul-2011.
One DATEADD, one DATEDIFF, and a division:
SELECT DATEADD(year,DATEDIFF(month,'19010701','20110630')/12,'19010701')
Basically, you count the number of months since some arbitrary financial year's start date (I've picked 1901), divide that number by 12 (ignoring the remainder), and add that many years back to the same arbitrary year's start date.
I don't know if this is the most efficient, but it's fast at least...
create function dbo.FinancialYearStart
(
#CurrentDate datetime
)
returns datetime
as
begin
declare #CurrentYear int
,#FYDateThisYear datetime
,#FYDatePrevYear datetime
set #CurrentYear = datepart(year, #CurrentDate)
set #FYDateThisYear = '01-Jul-' + cast(#CurrentYear as varchar(4))
set #FYDatePrevYear = '01-Jul-' + cast(#CurrentYear-1 as varchar(4))
if #CurrentDate < #FYDateThisYear
begin
return #FYDatePrevYear
end
return #FYDateThisYear
end
Extract the year and month from the date. Then do year = year + FLOOR((month-7) / 6)
Then your date is 1-jul-year
(You don't actually need to store them as variables.)
Something like: CONCATENATE('01-jul-', YEAR(date) + FLOOR((MONTH(date)-7) / 6)
A somewhat sophisticated method (maybe a tiny little bit too much):
SELECT
DATEADD(month,
(MONTH(GETDATE()) - 1) / 6 * 12 - 6,
CAST(CAST(YEAR(GETDATE()) AS varchar) AS datetime)
)
Clunky but it works
select
cast('01-Apr-' +
cast(
case
when datepart(mm,getdate()) in (4,5,6,7,8,9,10,11,12)
then DATEPART(yy,getdate())
else DATEPART(yy,getdate())-1
end as varchar
) as datetime
) as fy_start
SELECT cast(cast(YEAR(getdate())-
(case
when MONTH(GETDATE()) between 1 and 6 then 1
else 0
end) as varchar)+'0701' as date)
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