SQL Query Help: Transformation de dates de manière non triviale
-
01-07-2019 - |
Question
J'ai une table avec un " Date " colonne, et je voudrais faire une requête qui fait ce qui suit:
Si la date est un lundi , mardi , mercredi ou jeudi , la date affichée doit être décalé d'un jour, comme dans
DATEADD(day, 1, [Date])Par contre, s'il s'agit d'un vendredi , la date affichée doit être incrémentée de 3 jours (c'est-à-dire qu'elle devient la suivante < em> lundi ).
Comment faire cela dans mon instruction SELECT? Comme dans,
SELECT somewayofdoingthis([Date]) FROM myTable
(Il s'agit de SQL Server 2000.)
La solution
Voici comment je le ferais. Je recommande une fonction comme ci-dessus si vous comptez l'utiliser dans d'autres endroits.
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]
Autres conseils
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
Essayez
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]
Je suppose que vous souhaitez également que samedi et dimanche passent au lundi suivant. Si ce n'est pas le cas, prenez le 1 sur (1,2,3,4,5) et supprimez la dernière clause 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
Vous pouvez également le faire en une seule ligne:
select dateadd(day, 1 + (datepart(weekday, [Date])/6) * (8-datepart(weekday, [Date])), [Date])
Cela ressemble à une expression CASE. Je ne connais pas les manipulations de données appropriées pour SQL Server, mais cela ressemblerait à ceci:
CASE
WHEN [Date] is a Friday THEN DATEADD( day, 3, [Date] )
ELSE DATEADD( day, 1, [Date] )
END
Si vous souhaitez vérifier le week-end, vous pouvez ajouter des clauses WHEN avant ELSE.
vous pouvez utiliser ceci:
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
Recherchez l’instruction CASE et l’instruction DATEPART. Vous voudrez utiliser l'argument dw avec DATEPART pour récupérer un entier représentant le jour de la semaine.
Cela vient de ma tête et peut être clairement nettoyé, mais utilisez-le comme point de départ:
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
...
Pourquoi ne pas extraire une page de Data Warehouse et créer un tableau. En termes de DW, ce serait une dimension de date. Une dimension de date standard aurait des noms tels que différents noms pour une date (" MON " ;, " Lundi "," 22 août 1998 "), ou des indicateurs tels que la fin du mois et le début du mois. Cependant, vous pouvez également avoir des colonnes qui n’ont de sens que dans votre environnement.
Par exemple, en fonction de la question, la vôtre pourrait contenir une colonne indiquant le jour ouvrable suivant qui indiquerait la clé du jour en question. De cette façon, vous pouvez le personnaliser davantage pour prendre en compte les jours fériés ou les autres jours non ouvrables.
Les gens de DW sont intransigeants sur l’utilisation de clés sans signification (c’est-à-dire, n'utilisez pas simplement une date tronquée comme clé, utilisez une clé générée), mais vous pouvez en décider vous-même.
Le Date Dimension Toolkit contient du code permettant de générer vos propres tableaux dans divers SGBD, et CSV. données pour plusieurs années de dates.
vous devez créer une fonction SQL qui effectue cette transformation pour vous.
Cela ressemble en grande partie à celui de Brian, sauf qu'il n'a pas été compilé en raison d'inadéquations entre les parens et que j'ai modifié le SI pour qu'il ne contienne pas la sélection. Il est important de noter que nous utilisons DateNAME ici plutôt que datePART car datePART dépend de la valeur définie par SET DATEFIRST, qui définit le premier jour de la semaine.
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