SQL Query Help: Transformando datas em um não-trivial Way
-
01-07-2019 - |
Pergunta
Eu tenho uma tabela com uma coluna "Data", e eu gostaria de fazer uma consulta que faz o seguinte:
Se a data é um Segunda-feira , Terça-feira , Quarta-feira ou Quinta-feira , a data exibida deve ser deslocou-se por um dia, como em
DATEADD(day, 1, [Date])por outro lado, se é um Sexta-feira , a data exibida deve ser incrementado por 3 dias (ou seja, para que se torne o seguinte segunda-feira ).
Como posso fazer isso no meu instrução SELECT? Como em,
SELECT somewayofdoingthis([Date]) FROM myTable
(Este é o SQL Server 2000).
Solução
Aqui está como eu faria isso. Eu recomendo uma função como acima se você vai usar isso em outros lugares.
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]
Outras dicas
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
Tente
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]
Estou assumindo que você também quer sábado e domingo para deslocar para a frente para a segunda-feira seguinte. Se isso não for o caso, tomar a 1 de (1,2,3,4,5) e remover o último quando cláusula.
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
Você também pode fazê-lo em uma linha:
select dateadd(day, 1 + (datepart(weekday, [Date])/6) * (8-datepart(weekday, [Date])), [Date])
soa como uma expressão CASE. Eu não sei as manipulações de dados adequadas para SQL Server, mas basicamente ficaria assim:
CASE
WHEN [Date] is a Friday THEN DATEADD( day, 3, [Date] )
ELSE DATEADD( day, 1, [Date] )
END
Se você quiser verificar se há dias de fim de semana você pode adicionar adicional quando as cláusulas antes da outra pessoa.
Você pode utilizar isto:
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
Procure a instrução CASE ea declaração DATEPART. Você vai querer usar o argumento dw com DATEPART para voltar um inteiro que representa o dia da semana.
Este é fora do topo da minha cabeça e pode ser claramente limpo, mas usá-lo como ponto de partida:
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
...
Que tal tomar uma página do caras Data Warehouse e fazer uma tabela. Em termos DW, esta seria uma dimensão de data. A dimensão de data padrão teria coisas como vários nomes para uma data ( "MON", "Monday" "22 de agosto de 1998"), ou indicadores como fim-de-mês e de início de mês. No entanto, você também pode ter colunas que só fazem sentido no seu ambiente.
Por exemplo, com base na pergunta, a sua pode ter uma coluna próxima-dia de trabalho que apontam para a chave para o dia em questão. Dessa forma, você pode personalizá-lo ainda mais para tomar em consideração os feriados ou outros dias não úteis.
O pessoal DW são inflexíveis sobre como utilizar teclas sem sentido (ou seja, não basta usar uma data truncado como a chave, use uma chave gerada), mas você pode decidir isso por si mesmo.
O Data Dimension Toolkit tem código para gerar suas próprias tabelas em vários DBMS e tem CSV dados para vários anos no valor de datas.
você precisa criar uma função SQL que faz essa transformação para você.
Isto é principalmente como Brian de exceto que ele não compilar devido a parens incompatíveis e eu mudei o IF para não ter a escolha nele. É importante notar que usamos DATENAME aqui em vez de datepart porque datepart é dependente do valor definido pelo SET DATEFIRST, que define o primeiro dia da semana.
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