Справка по SQL-запросу:Преобразование дат нетривиальным способом

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

Вопрос

У меня есть таблица со столбцом "Дата", и я хотел бы выполнить запрос, который выполняет следующее:

Если дата является Понедельник, Вторник, Среда, или Четверг, отображаемая дата должна быть сдвинута вверх на 1 день, как в

DATEADD(day, 1, [Date])
С другой стороны, если это Пятница, отображаемая дата должна быть увеличена на 3 дня (т. е.таким образом, это становится следующим Понедельник).

Как мне сделать это в моем операторе SELECT?Как в,

SELECT somewayofdoingthis([Date]) FROM myTable

(Это SQL Server 2000.)

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

Решение

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

CASE
WHEN
    DATEPART(dw, [Date]) IN (2,3,4,5)
THEN
    DATEADD(d, 1, [Date])
WHEN
    DATEPART(dw, [Date]) = 6
THEN
    DATEADD(d, 3, [Date])
ELSE
    [Date]
END AS [ConvertedDate]

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

CREATE FUNCTION dbo.GetNextWDay(@Day datetime)
RETURNS DATETIME
AS
BEGIN 
    DECLARE @ReturnDate DateTime

    set @ReturnDate = dateadd(dd, 1, @Day)

    if (select datename(@ReturnDate))) = 'Saturday'
        set @ReturnDate = dateadd(dd, 2, @ReturnDate)

    if (select datename(@ReturnDate) = 'Sunday'
        set @ReturnDate = dateadd(dd, 1, @ReturnDate)

    RETURN @ReturnDate
END

Попробуй

select case  when datepart(dw,[Date]) between 2 and 5 then DATEADD(dd, 1, [Date])
when datepart(dw,[Date]) = 6 then DATEADD(dd, 3, [Date]) else [Date] end as [Date] 

Я предполагаю, что вы также хотите, чтобы суббота и воскресенье были перенесены на следующий понедельник.Если это не так, уберите 1 из (1,2,3,4,5) и удалите последнее предложение when.

case
   --Sunday thru Thursday are shifted forward 1 day
   when datepart(weekday, [Date]) in (1,2,3,4,5) then dateadd(day, 1, [Date]) 
   --Friday is shifted forward to Monday
   when datepart(weekday, [Date]) = 6  then dateadd(day, 3, [Date])
   --Saturday is shifted forward to Monday
   when datepart(weekday, [Date]) = 7  then dateadd(day, 2, [Date])
end

Вы также можете сделать это в одной строке:

select dateadd(day, 1 + (datepart(weekday, [Date])/6) * (8-datepart(weekday, [Date])), [Date])

Звучит как ПАДЕЖНОЕ выражение.Я не знаю, как правильно манипулировать данными для SQL Server, но в основном это выглядело бы так:

CASE
  WHEN [Date] is a Friday THEN DATEADD( day, 3, [Date] )
  ELSE DATEADD( day, 1, [Date] )
END

Если вы хотите проверить наличие выходных дней, вы могли бы добавить дополнительные предложения WHEN перед ELSE.

вы могли бы использовать это:

select dayname,newdayname =
    CASE dayname
    WHEN 'Monday' THEN 'Tuesday'
    WHEN 'Tuesday' THEN 'Wednesday'
    WHEN 'Wednesday' THEN 'Thursday'
    WHEN 'Thursday' THEN 'Friday'
    WHEN 'Friday' THEN 'Monday'
    WHEN 'Saturday' THEN 'Monday'
    WHEN 'Sunday' THEN 'Monday'
END
FROM UDO_DAYS
results:
Monday       Tuesday
Tuesday      Wednesday
Wednesday    Thursday
Thursday     Friday
Friday       Monday
Saturday     Monday
Sunday       Monday

table data:
Monday
Tuesday
Wednesday
Thursday
Friday
Saturday
Sunday

Посмотрите инструкцию CASE и инструкцию DATEPART.Вы захотите использовать аргумент dw с DATEPART, чтобы получить обратно целое число, представляющее день недели.

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

select case when DATENAME(dw, [date]) = 'Monday' then DATEADD(dw, 1, [Date])
                when DATENAME(dw, [date]) = 'Tuesday' then DATEADD(dw, 1, [Date])
                when DATENAME(dw, [date]) = 'Wednesday' then DATEADD(dw, 1, [Date])
                when DATENAME(dw, [date]) = 'Thursday' then DATEADD(dw, 1, [Date])
                when  DATENAME(dw, [date]) = 'Friday' then DATEADD(dw, 3, [Date])
          end as nextDay
    ...

Как насчет того, чтобы взять страницу из Хранилище данных ребята, накрывайте стол.В терминах DW это было бы измерение даты.A стандартный размер даты были бы такие вещи, как различные названия для даты ("ПН", "Понедельник", "22 августа 1998"), или такие индикаторы, как конец месяца и начало месяца.Однако у вас также могут быть столбцы, которые имеют смысл только в вашей среде.

Например, исходя из вопроса, в вашем может быть столбец "следующий рабочий день", который будет указывать на ключ для рассматриваемого дня.Таким образом, вы можете дополнительно настроить его с учетом праздничных или других нерабочих дней.

Ребята из DW непреклонны в использовании бессмысленных ключей (то есть не просто используйте усеченную дату в качестве ключа, используйте сгенерированный ключ), но вы можете решить это сами.

Тот Самый Инструментарий Измерения даты содержит код для создания ваших собственных таблиц в различных СУБД и содержит CSV-данные за несколько лет.

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

Это в основном похоже на Brian's, за исключением того, что оно не компилировалось из-за несовпадения скобок, и я изменил IF, чтобы в нем не было select.Важно отметить, что здесь мы используем DateNAME, а не datePART, потому что datePART зависит от значения, установленного SET DATEFIRST , которое устанавливает первый день недели.

CREATE FUNCTION dbo.GetNextWDay(@Day datetime)
RETURNS DATETIME
AS
BEGIN
    DECLARE @ReturnDate DateTime

    set @ReturnDate = dateadd(dd, 1, @Day)
    if datename(dw, @ReturnDate) = 'Saturday'
        set @ReturnDate = dateadd(dd, 2, @ReturnDate)
    if datename(dw, @ReturnDate) = 'Sunday'
        set @ReturnDate = dateadd(dd, 1, @ReturnDate)
    RETURN @ReturnDate
END
create table #dates (dt datetime)
insert into #dates (dt) values ('1/1/2001')
insert into #dates (dt) values ('1/2/2001')
insert into #dates (dt) values ('1/3/2001')
insert into #dates (dt) values ('1/4/2001')
insert into #dates (dt) values ('1/5/2001')

    select
        dt, day(dt), dateadd(dd,1,dt)
    from
        #dates
    where
        day(dt) between 1 and 4

    union all

    select
        dt, day(dt), dateadd(dd,3,dt)
    from
        #dates
    where
        day(dt) = 5

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