Справка по SQL-запросам: преобразование дат нетривиальным способом - PullRequest
3 голосов
/ 19 сентября 2008

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

Если дата понедельник , вторник , среда или четверг , отображаемая дата должна быть смещена на 1 день, как в

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

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

SELECT somewayofdoingthis([Date]) FROM myTable

(Это SQL Server 2000.)

Ответы [ 12 ]

5 голосов
/ 19 сентября 2008

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

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]
4 голосов
/ 19 сентября 2008
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
2 голосов
/ 19 сентября 2008

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

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])
2 голосов
/ 19 сентября 2008

Попробуйте

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 голос
/ 20 сентября 2008

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

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

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

Набор инструментов Date Dimension содержит код для создания собственных таблиц в различных СУБД и данные CSV за несколько лет.

1 голос
/ 19 сентября 2008

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

1 голос
/ 19 сентября 2008

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

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
1 голос
/ 19 сентября 2008

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

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
    ...
1 голос
/ 19 сентября 2008

Звучит как выражение CASE. Я не знаю правильных манипуляций с данными для SQL Server, но в основном это выглядело бы так:

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

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

0 голосов
/ 20 сентября 2008

Это в основном похоже на Брайан, за исключением того, что он не компилировался из-за несоответствующих паренов, и я изменил IF, чтобы в нем не было выбора. Важно отметить, что мы используем 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
...