Converting the name of a day to its integer representation
-
23-08-2019 - |
Question
In SQL server you can use the DATENAME function to get the day of week as a string
declare @date datetime
set @date = '12/16/08'
select datename(dw, @date)
which returns "Tuesday"
and you can use the DATEPART function to get the day of week as an integer
declare @date datetime
set @date = '12/16/08'
select datepart(dw, @date)
Which returns 3
But say I have a varchar that contains the string "Tuesday" and I want to convert it to its integer representation of 3. Sure, I could write out the conversion without much hassle, but I'd much rather use a built-in function. Does such a function exist?
Solution
Rather than write a function, you should create a days of the week table with the description and the numeric value. THen you can simply join to the table to get the numeric.
And if you have days stored multiple ways (likely in a characterbased system), you can put all the variants into the table, so TUE, Tues., Tuesday would all map to the same integer.
OTHER TIPS
unfortunately there isn't a built in function, but you can create your own like this:
CREATE FUNCTION dbo.WeekDay(@DayOfWeek Varchar(9))
RETURNS INT
AS
BEGIN
DECLARE @iDayofWeek INT
SELECT @iDayofWeek = CASE @DayOfWeek
WHEN 'Sunday' THEN 1
WHEN 'Monday' THEN 2
WHEN 'Tuesday' THEN 3
WHEN 'Wednesday' THEN 4
WHEN 'Thursday' THEN 5
WHEN 'Friday' THEN 6
WHEN 'Saturday' THEN 7
END
RETURN (@iDayofWeek)
END
GO
Well 6 years later and several version of SQL Server but there still no built-in function to do this (as far as I know). Not sure if sql-server-2014 will something to do this.
I took similar approach to @RussBradberry just done with IF
statements.
CREATE FUNCTION dbo.WeekDayInt (@DayOfWeekName VARCHAR(10))
RETURNS INT
AS
BEGIN
DECLARE @DayWeekNumber INT
IF @DayOfWeekName = 'Sunday' SET @DayWeekNumber = 1
IF @DayOfWeekName = 'Monday' SET @DayWeekNumber = 2
IF @DayOfWeekName = 'Tuesday' SET @DayWeekNumber = 3
IF @DayOfWeekName = 'Wednesday' SET @DayWeekNumber = 4
IF @DayOfWeekName = 'Thursday' SET @DayWeekNumber = 5
IF @DayOfWeekName = 'Friday' SET @DayWeekNumber = 6
IF @DayOfWeekName = 'Saturday' SET @DayWeekNumber = 7;
RETURN (@DayWeekNumber)
END
or as alternative it can be done this way, which can be a little faster because it will return value as soon as match is encountered and not try to evaluate other values.
CREATE FUNCTION dbo.WeekDayInt (@DayOfWeekName VARCHAR(10))
RETURNS INT
AS
BEGIN
IF @DayOfWeekName = 'Sunday' RETURN 1
IF @DayOfWeekName = 'Monday' RETURN 2
IF @DayOfWeekName = 'Tuesday' RETURN 3
IF @DayOfWeekName = 'Wednesday' RETURN 4
IF @DayOfWeekName = 'Thursday' RETURN 5
IF @DayOfWeekName = 'Friday' RETURN 6
IF @DayOfWeekName = 'Saturday' RETURN 7;
RETURN 0;
END
Here is a dirty alternative that I use if I'm not running it on massive dataset.
Select CHARINDEX(SUBSTRING('Thursday',1,3), 'MONTUEWEDTHUFRISATSUN') / 3 + 1
Just replace Thursday with a day of your choice or a variable.
How it works: SUBSTRING('Thursday',1,3) basically creates Thu, then charindex finds out the position of thu in the string which is 10. We then divide 10 by length of our day words which is 3 which equals 3, and because I want
Monday to equal 1 Tuesday to equal 2 Wednesday to equal 3 Thursday to equal 4
I add 1 to the end
so the result is 4.
Hope that helps someone, but I agree it probably isn't the best solution.
Note: You can also order a result set by day number by using it like so:
SELECT ID,DayNamesColumn from mytable ORDER BY CHARINDEX(SUBSTRING(DayNamesColumn ,1,3), 'MONTUEWEDTHUFRISATSUN') / 3 + 1
You can use the following select to get the iso weekday ordinal of date 2017-12-15
with respect to (e.g. regardless of) the current setting of @@datefirst which determines the first day of the week. E.g. set datefirst = 1 for monday.
select
w.weekday_id_iso8601,
w.weekday_id_datepart,
w.weekday_name
from (
values
(7, 'Monday'),
(8, 'Tuesday'),
(9, 'Wednesday'),
(10, 'Thursday'),
(11, 'Friday'),
(12, 'Saturday'),
(13, 'Sunday'))
t(weekday_id, weekday_name)
cross apply (
select
t.weekday_id - 6 weekday_id_iso8601,
(t.weekday_id - @@datefirst + 1) % 7 + 1 weekday_id_datepart,
t.weekday_name
) w
where w.weekday_id_datepart = datepart(weekday, '2017-12-15')
I disagree with the answer about adding a lookup table, since in this case, the values are limited and will never change. The lookup table join will just add cost.
IMHO; since you have limited values, I would just use a case statement in my views. It's not pretty, but it's probably the fastest way to do it.
This may not serve a practical purpose, but I thought I'd figure it out just for fun. :) The following works.
Remember that when using DATEPART or DATENAME that the value of @@DATEFIRST is important and can change your results. Look up SET DATEFIRST in the online help.
DECLARE
@date_name AS VARCHAR(20)
SET @date_name = 'Monday'
SELECT
DATEPART(dw, my_date)
FROM
(
SELECT CAST('1900-01-01' AS DATETIME) AS my_date UNION
SELECT CAST('1900-01-02' AS DATETIME) AS my_date UNION
SELECT CAST('1900-01-03' AS DATETIME) AS my_date UNION
SELECT CAST('1900-01-04' AS DATETIME) AS my_date UNION
SELECT CAST('1900-01-05' AS DATETIME) AS my_date UNION
SELECT CAST('1900-01-06' AS DATETIME) AS my_date UNION
SELECT CAST('1900-01-07' AS DATETIME) AS my_date
) AS My_Dates
WHERE
DATENAME(dw, my_date) = @date_name
Where DayID
is integer value 1 thru 7.
Add DayID to a some base date such as 1899-12-31. (If Sunday is first day of week then use initial date of 1899-12-30)
1900-01-01 was Monday, 1900-01-02 was Tuesday, and so on.
Thus :
select DayID,
datename( weekday, dateadd( day, DayID, '18991231' ) )
In SQL 2014, you can use:
SELECT DATEPART(DW, GetDate()) This will return day of week as integer.