Convert month name to month number in SQL Server - sql-server

In T-SQL what is the best way to convert a month name into a number?
E.g:
'January' -> 1
'February' -> 2
'March' -> 3
Etc.
Are there any built in functions that can do this?

How about this?
select DATEPART(MM,'january 01 2011') -- returns 1
select DATEPART(MM,'march 01 2011') -- returns 3
select DATEPART(MM,'august 01 2011') -- returns 8

How about this:
SELECT MONTH('March' + ' 1 2014')
Would return 3.

Its quit simple,
Take the first 3 digits of the month name and use this formula.
Select charindex('DEC','JAN FEB MAR APR MAY JUN JUL AUG SEP OCT NOV DEC')/4+1

SELECT DATEPART(MM,'january '+'01 1900')
SELECT MONTH('january ' + '01 1900')
SELECT month(dateadd(month,DATEDIFF(month,0,'january 01 2015'),0))

You can create a function and then refer to it in the select statement.
The function may look similar to this:
if OBJECT_ID('fn_month_name_to_number', 'IF') is not null
drop function fn_month_name_to_number
go
create function fn_month_name_to_number (#monthname varchar(25))
returns int as
begin
declare #monthno as int;
select #monthno =
case #monthname
when 'January' then 1
when 'February' then 2
when 'March' then 3
when 'April' then 4
when 'May' then 5
when 'June' then 6
when 'July' then 7
when 'August' then 8
when 'September' then 9
when 'October' then 10
when 'November' then 11
when 'December' then 12
end
return #monthno
end
Then you can query it.
select fn_month_name_to_number ('February') as month_no
This query will return 2 as month number.
You can pass values from a column as parameters to the function.
select fn_month_name_to_number (*columnname*) as month_no from *tablename*
Have a good day!

There is no built in function for this.
You could use a CASE statement:
CASE WHEN MonthName= 'January' THEN 1
WHEN MonthName = 'February' THEN 2
...
WHEN MonthName = 'December' TNEN 12
END AS MonthNumber
or create a lookup table to join against
CREATE TABLE Months (
MonthName VARCHAR(20),
MonthNumber INT
);
INSERT INTO Months
(MonthName, MonthNumber)
SELECT 'January', 1
UNION ALL
SELECT 'February', 2
UNION ALL
...
SELECT 'December', 12;
SELECT t.MonthName, m.MonthNumber
FROM YourTable t
INNER JOIN Months m
ON t.MonthName = m.MonthName;

I recently had a similar experience (sql server 2012). I did not have the luxury of controlling the input, I just had a requirement to report on it. Luckily the dates were entered with leading 3 character alpha month abbreviations, so this made it simple & quick:
TRY_CONVERT(DATETIME,REPLACE(obs.DateValueText,SUBSTRING(obs.DateValueText,1,3),CHARINDEX(SUBSTRING(obs.DateValueText,1,3),'...JAN,FEB,MAR,APR,MAY,JUN,JUL,AUG,SEP,OCT,NOV,DEC')/4))
It worked for 12 hour:
Feb-14-2015 5:00:00 PM 2015-02-14 17:00:00.000
and 24 hour times:
Sep-27-2013 22:45 2013-09-27 22:45:00.000
(thanks ryanyuyu)

I think you may even have a separate table like a monthdetails (Monthno int, monthnames char(15)) and include values:
1 January
2 February
.... and so on, and then join this table with your existing table in the monthnames column
SELECT t1.*,t2.Monthno from table1
left outer join monthdetails t2
on t1.monthname=t2.monthnames
order by t2.Monthno

You can use below code
DECLARE #T TABLE ([Month] VARCHAR(20))
INSERT INTO #T
SELECT 'January'
UNION
SELECT 'February'
UNION
SELECT 'March'`
SELECT MONTH('01-' + [Month] + '-2010') As MonthNumeric,[Month] FROM #T
ORDER BY MonthNumeric

You can try sth like this, if you have month_name which is string datetype.After converting, you can feel free to order by Month.
For example, your table like this:
month
Dec
Jan
Feb
Nov
Mar
.
.
.
My syntax is:
Month(cast(month+'1 2016' as datetime))

You can do it this way, if you have the date (e.g. SubmittedDate)
DATENAME(MONTH,DATEADD(MONTH, MONTH(SubmittedDate) - 1, 0)) AS ColumnDisplayMonth
Or you can do it this way, if you have the month as an int
DATENAME(MONTH,DATEADD(MONTH, #monthInt - 1, 0)) AS ColumnDisplayMonth

I know this may be a bit too late but the most efficient way of doing this through a CTE as follows:
WITH Months AS
(
SELECT 1 x
UNION all
SELECT x + 1
FROM Months
WHERE x < 12
)
SELECT x AS MonthNumber, DateName( month , DateAdd( month , x , -1 )) AS MonthName FROM Months

try this
SELECT EXTRACT(MONTH FROM TO_DATE(month_added, 'Month')) AS month_number

select Convert(datetime, '01 ' + Replace('OCT-12', '-', ' '),6)

Related

How can I convert YYWW to date format based on day[Ex: Monday's date in given YYWW ] in SqlServer?

I have a column in my table with YYWW format. I need to convert this YYWW and get Monday's date.
For Example:
Input YYWW: 1847
Expected Output: 2018-11-19 [Monday's date in 2018 Week 47]
Thanks in advance
I tried the below but does not work properly
declare #value int = 1519
SELECT CONVERT(VARCHAR(10), DATEADD(YEAR, 2000 + #value / 100-1900, 7 * (#value % 100)-7), 105);
1851 -Expected 17-12-2018[Monday] Works fine for this year 2018
1752 -Expected 25-12-2017[Monday] but shows 24-12-2017 [Sunday]
1652 -Expected 26-12-2016 [Monday] but shows 24-12-2016 [Saturday]
1519 -Expected 04-05-2015 [Monday] but shows 07-05-2015 [Thursday]
Try this:
DECLARE #t table(YYWW char(4))
INSERT #t values('1847'),('1752'),('1652'),('1519')
SELECT
CAST(DATEADD(wk,RIGHT(YYWW,2)+DATEDIFF(d,0,DATEADD(
d,-4,LEFT(YYWW,2)+'0101'))/7,0) as date)
FROM #t
Result:
2018-11-19
2017-12-25
2016-12-26
2015-05-04
EDIT:
To get the requested format DD-MM-YYYY:
SELECT
CONVERT(CHAR(10),DATEADD(wk,RIGHT(YYWW,2)+DATEDIFF(d,0,DATEADD(
d,-4,LEFT(YYWW,2)+'0101'))/7,0),105)
FROM #t
I would, personally, use a calendar table. Then you can do something like:
SELECT YT.YYWW,
CT.[date]
FROM YourTable YT
JOIN CalendarTable CT ON CT.[Year] = '20'+LEFT(YT.YYWW,2)
AND CT.WeekNo = RIGHT(YT.YYWW,2)
AND CT.DayOfWeek = 1; --Assumes Monday is day 1.
I think your calc may be off week 47 of 2018 starts on 2018-11-26 which is a Monday.
in any case the following should work if you disagree with the above simply subtract 1 from the number of weeks
DECLARE #Date date
DECLARE #Year int = 2000 +18
declare #week int = 47
SET #Date = DATEADD(YEAR, #Year - 1900, 0)
SELECT dateadd(ww,#week-1,DATEADD(DAY, (##DATEFIRST - DATEPART(WEEKDAY, #Date) + (8 - ##DATEFIRST) * 2) % 7, #Date))

Conditional scoring

I have a table that shows only the 'captured' data. For example in the below exhibit, the emp_no 17 has 2 records - for November and February (for a specified 6 month period, from July 2017). It does not have data for the other 4 months (within the 6-month date range, from previous 6 months to current date).
How can I populate these missing months (Sept, Oct, Dec) with default values for num_differences of 0 for the missing months? (for example, in this case, I want emp_no 17 to have the below (I can ignore 2018 data - only require data up to Dec 2017):
I have the script below:
declare #YMN date;
set #YMN = '20171201';
DECLARE #Emp TABLE (
[date] date,
[emp_no] int,
[num_differences] int
);
INSERT INTO #Emp VALUES
('2017-09-14', 17, 1), ('2017-12-01', 17, 1),('2017-12-18', 17, 1),('2017-12-21', 17, 1),
('2017-09-27', 17, 1), ('2017-12-04', 17, 1);
-------------------------------------------------------------------------------------------get missing dates---------------------------------------------------------------------------
;WITH cte_Emp_No AS (
SELECT DISTINCT [emp_no]
FROM #Emp
),
cte_dates AS (
SELECT [emp_no], DATEADD(month, -6, DATEADD(dd, -(DAY(dateadd(month, 1, #YMN)) - 1), dateadd(month, 1, #YMN))) AS [date]
FROM cte_Emp_No
UNION ALL
SELECT [emp_no], DATEADD(month, 1, [date]) AS [date]
FROM cte_dates
WHERE [date] < dateadd(month, 0, #YMN)
)
SELECT DISTINCT ISNULL(e.emp_no, c.emp_no) emp_no, ISNULL(e.date, c.date) date, ISNULL(e.num_differences, 0) num_differences
into ##new_table
FROM #Emp AS e
RIGHT JOIN cte_dates AS c ON YEAR(c.date) = YEAR(e.date) AND MONTH(c.date) = MONTH(e.date)
-----------------------------------------------------------------------------------------------MAIN CTE------------------------------------------------------------------------------
;with cte_RawScore as
(
select emp_no
, date YMN
,sum(case when datediff(month, convert(datetime, #YMN, 112), date) = 0 then num_differences else 0 end) as thismonth
,sum(case when datediff(month, convert(datetime, #YMN, 112), date) between -2 and 0 then num_differences else 0 end) as last3month
,sum(case when datediff(month, convert(datetime, #YMN, 112), date) between -5 and 0 then num_differences else 0 end) as last6month
from ##new_table d
group by emp_no, date
)
select
emp_no
,YMN
,case when last6month = 0 then 5
when last3month = 0 then 4
when thismonth = 0 then 3
when thismonth <= 3 then 2
else 1 end RawScore
from cte_RawScore
ORDER BY day(YMN) desc
drop table ##new_table
I want this the scoring only to be applicable for 6 months from and after July 2017. i.e. the #YMN is a variable that stores the year month number; and the score, according to the above rule applies to the 6 months from 201707.
So 201707 is 1 month,
201708 is 2 months, etc, up to 201712
I wish to have a list of employees with their associated scores, based on the rules mentioned below .
That’s, :
A score of 5 if 0 differences in 6 consecutive months ( from July to December) ;
A score of 4 if 0 differences in 3 consecutive months (from July to December);
A score of 3 if 0 differences for 1 month ( from July to December);
A score of 2 if 1 to 3 differences for 1 month (from July to December);
A score of 1 if 4 or more differences in 1 month (from July to December).
I get the number of differences from a table, but some employees do not appear for certain months; hence I want to give them a difference of 0 if they do not appear for that particular month.
Please assist.
I think I understand what you're getting at. Let me give you a simplified example. You need a table full of dates to join to. In data warehousing we use a Date dimension which has attributes about every date.
For your example your date dimension table could just have Month names or numbers:
1
2
...
12
Let's call this table Months.
Then you would do something like this, to count a zero for months with no data. Here I'm using what's called a Common Table Expression or CTE (the part with the WITH) in place of a table, since I'm not concerned with creating a permanent table right now.
WITH Months AS (
SELECT 1 AS MonthNumber UNION
SELECT 2 UNION
SELECT 3 UNION
SELECT 4 UNION
SELECT 5 UNION
SELECT 6 UNION
SELECT 7 UNION
SELECT 8 UNION
SELECT 9 UNION
SELECT 10 UNION
SELECT 11 UNION
SELECT 12
)
SELECT M.MonthNumber, COUNT(*)
FROM Months as M
LEFT JOIN MyData as D
ON MONTH(D.SomeDateValue) = M.MonthNumber
GROUP BY M.MonthNumber
This will guarantee every month appears with a count, perhaps of zero.

SQL Server to Oracle to find number of months

I just did query to find the number of months between two dates (except current month) in SQL Server:
SELECT
(DATEDIFF(MONTH, DATEADD(MONTH, 1, '2016-02-20 00:00:00.000') -
DAY(DATEADD(MONTH, 1, '2016-02-20 00:00:00.000')), '2016-12-31 00:00:00.000'))
The above will return 10 .. how do we achieve this in Oracle?
I guess - atleast in 10g and above - the correct function is
SELECT MONTHS_BETWEEN([date1],[date2]) FROM dual
Furthermore it is possible to calculate the difference between two dates
SELECT [date2] - [date1] FROM dual
This will give you the difference in days.
There are several different ways to count a difference in months;
a good starting point could be months_between:
SQL> with testDates (date1, date2) as
2 (
3 select date '2016-12-31', date '2016-02-20' from dual union all
4 select date '2016-02-01', date '2016-01-31' from dual union all
5 select date '2016-12-30', date '2016-11-30' from dual union all
6 select date '2016-12-29', date '2016-11-30' from dual
7 )
8 select date1, date2, months_between(date1, date2) diff, floor(months_between(date1, date2) ) floor_diff
9 from testDates;
DATE1 DATE2 DIFF FLOOR_DIFF
--------- --------- ---------- ----------
31-DIC-16 20-FEB-16 10,3548387 10
01-FEB-16 31-GEN-16 ,032258065 0
30-DIC-16 30-NOV-16 1 1
29-DIC-16 30-NOV-16 ,967741935 0
The Right query to find the sum of months between two dates in Oracle11g..Please try it
SELECT COUNT(0) TOTAL_MONTHS
FROM (SELECT DATE '2015-01-05' START_DATE,
DATE '2015-12-15' END_DATE
FROM DUAL)
CONNECT BY LEVEL <= MONTHS_BETWEEN(
TRUNC(END_DATE,'MM'),
TRUNC(START_DATE,'MM') )
+ 1

How to create stored procedure for alternative working Saturdays?

I want to create a stored procedure for displaying working Saturdays.
For example:
Last working Saturday 08/08/2015 (dd/mm/yyyy), then next working Saturday should be 22/08/2015 (dd/mm/yyyy)
It should omit between Saturday (15/08/2015). Likewise, I want to show for particular year
Try this. The assumption is, 3rd Jan 2015 was the first working Saturday.
DECLARE #firstsaturday date = '2015-01-03'
;WITH CTE AS
(
SELECT #firstsaturday AS StartDate
UNION ALL
SELECT DATEADD(WK,2,StartDate)
FROM CTE
WHERE YEAR(StartDate) = '2015'
)
SELECT * FROM CTE
WHERE YEAR(StartDate) = '2015'
Try something like this
DECLARE #start_sat_day DATE = Dateadd(d, -( Datepart(dw, Getdate()) % 7 ), Getdate());
WITH cte
AS (SELECT #start_sat_day AS sat_days
UNION ALL
SELECT Dateadd(dd, 14, sat_days)
FROM cte
WHERE Year(sat_days) = Year(#start_sat_day))
SELECT sat_days
FROM cte
WHERE Year(sat_days) = Year(#start_sat_day)
Result :
sat_days
---------
2015-08-08
2015-08-22
2015-09-05
2015-09-19
2015-10-03
2015-10-17
2015-10-31
2015-11-14
2015-11-28
2015-12-12
2015-12-26

Adding a Month Name Sort within T-SQL Code

Could you please help me hardcode into the T-SQL SELECT statement below a CalendarMonth Sort so when someone queries the data it comes out Jan, Feb not Apr, Aug. I have already done this for the FinancialMonth row but struggling with the CalendarMonth.
BEGIN
INSERT INTO Time3(Date,CalendarYear,CalendarMonth,FinancialYear,FinancialMonth)
SELECT
#StartDate Date,YEAR(#StartDate) AS CalendarYear,
DATENAME(MONTH,#StartDate) AS CalendarMonth,
YEAR(Dateadd(MONTH,-3,#StartDate)) AS FinancialYear,
'Period ' + RIGHT('0' + CAST(MONTH(Dateadd(MONTH, -3,#StartDate)) AS VARCHAR(2)),2) AS FinancialMonth
SET #StartDate = DATEADD(dd,1,#StartDate)
END
Try this:
ORDER BY MONTH(#StartDate)
MONTH is the function which returns an integer that represents the month of the specified date.
http://msdn.microsoft.com/ru-ru/library/ms187813.aspx
simply add an extra column to your query that looks like this, just replace #Month with your variable:
CASE #Month
WHEN 'January' THEN 1
WHEN 'February' THEN 2
WHEN 'March' THEN 3
WHEN 'April' THEN 4
WHEN 'May' THEN 5
WHEN 'June' THEN 6
WHEN 'July' THEN 7
WHEN 'August' THEN 8
WHEN 'September' THEN 9
WHEN 'October' THEN 10
WHEN 'November' THEN 11
WHEN 'December' THEN 12
END as MonthOrder
and then in your ORDER BY clause, order by this column

Resources