Преобразование названия дня в его целочисленное представление

StackOverflow https://stackoverflow.com/questions/387434

  •  23-08-2019
  •  | 
  •  

Вопрос

На сервере SQL вы можете использовать функцию DATENAME, чтобы получить день недели в виде строки.

declare @date datetime
set @date = '12/16/08'
select datename(dw, @date)

который возвращает «вторник»

и вы можете использовать функцию DATEPART, чтобы получить день недели в виде целого числа.

declare @date datetime
set @date = '12/16/08'
select datepart(dw, @date)

Что возвращает 3

Но предположим, что у меня есть varchar, содержащий строку «Вторник», и я хочу преобразовать его в целочисленное представление 3.Конечно, я мог бы без особых хлопот написать преобразование, но я бы предпочел использовать встроенную функцию.Существует ли такая функция?

Это было полезно?

Решение

Вместо того, чтобы писать функцию, вам следует создать таблицу дней недели с описанием и числовым значением.Затем вы можете просто присоединиться к таблице, чтобы получить числовое значение.

А если у вас есть дни, хранящиеся несколькими способами (вероятно, в символьной системе), вы можете поместить все варианты в таблицу, чтобы TUE, Tues., Tuesday все отображались в одно и то же целое число.

Другие советы

к сожалению, встроенной функции нет, но вы можете создать свою собственную:


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

Что ж, 6 лет спустя и несколько версий SQL Server, но встроенной функции для этого до сих пор нет (насколько мне известно).Не уверен если будет что-то для этого сделать.

Я применил тот же подход, что и @RussBradberry, только что покончив с IF заявления.

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

или, в качестве альтернативы, это можно сделать таким образом, что может быть немного быстрее, поскольку оно будет возвращать значение, как только будет обнаружено совпадение, и не будет пытаться оценить другие значения.

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

Вот грязная альтернатива, которую я использую, если не использую ее на большом наборе данных.

    Select CHARINDEX(SUBSTRING('Thursday',1,3), 'MONTUEWEDTHUFRISATSUN') / 3 + 1

Просто замените четверг на день по вашему выбору или переменную.

Как это работает:SUBSTRING('Thursday',1,3) в основном создает четверг, затем charindex определяет позицию четверга в строке, которая равна 10.Затем мы делим 10 на длину наших дневных слов, то есть 3, что равно 3, и поскольку я хочу

Понедельник до равного 1 во вторник до равных 2 среды до 3 четверга до 4

добавляю 1 в конец

поэтому результат 4.

Надеюсь, это кому-то поможет, но я согласен, что это, вероятно, не лучшее решение.

Примечание:Вы также можете упорядочить набор результатов по номеру дня, используя его следующим образом:

SELECT ID,DayNamesColumn from mytable ORDER BY CHARINDEX(SUBSTRING(DayNamesColumn ,1,3), 'MONTUEWEDTHUFRISATSUN') / 3 + 1

Вы можете использовать следующий выбор, чтобы получить порядковый номер дня недели в формате ISO. 2017-12-15 относительно (напр.независимо от) текущей настройки @@datefirst, которая определяет первый день недели.Например.установите datefirst = 1 для понедельника.

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')

С ответом о добавлении справочной таблицы не согласен, так как в этом случае значения ограничены и никогда не изменятся.Соединение таблицы поиска только увеличит стоимость.

ИМХО;поскольку у вас ограниченные ценности, я бы просто использовал в своих взглядах оператор случая.Это некрасиво, но, вероятно, это самый быстрый способ сделать это.

Возможно, это не служит практической цели, но я подумал, что разберусь с этим просто ради развлечения.:) Работает следующее.

Помните, что при использовании DATEPART или DATENAME значение @@DATEFIRST важно и может изменить ваши результаты.Найдите SET DATEFIRST в онлайн-справке.

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

Где DayID является целочисленным значением от 1 до 7.

Добавьте DayID к некоторой базовой дате, например 1899-12-31.(Если воскресенье — первый день недели, используйте начальную дату 30 декабря 1899 г.)

1900-01-01 был понедельник, 1900-01-02 был вторник и так далее.

Таким образом :

select DayID, 
       datename( weekday, dateadd( day, DayID, '18991231' ) ) 

В SQL 2014 вы можете использовать:

SELECT DATEPART(DW, GetDate()) Возвращает день недели в виде целого числа.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top