-1
votes

SQL Server trouve des lignes approchant un jour et un mois de service

J'ai un tableau qui répertorie les équipements avec une date d'installation. Ces articles doivent être révisés annuellement ou tous les cinq ans. Ainsi, les lignes ont un intervalle de service de 1 ou 5. Quelque chose comme:

select top 20
    MONTH(InstallationDate) as InstallMonth,
    Day(InstallationDate) as InstallDay,
    format(InstallationDate,'MMM dd yyyy') as Installed,
    case WHEN DATEFROMPARTS(year(getdate()),month(InstallationDate),day(InstallationDate)) < getdate()
    then dateadd(year,1, DATEFROMPARTS(year(getdate()),month(InstallationDate),day(InstallationDate)) )
    else   DATEFROMPARTS(year(getdate()),month(InstallationDate),day(InstallationDate))
    end as ServiceDue,
    case when year(InstallationDate) + 5 = year(getdate()) then '5 year service due' 
    when year(InstallationDate) + 5 < year(getdate()) then '5 year service passed' 
    when year(InstallationDate) + 5 > year(getdate()) then 'Five year service due ' + cast(year(InstallationDate) + 5 as varchar)
    end as '5 Year Service',

    case when year(InstallationDate) + 10 = year(getdate()) then '10 year service due' 
    when year(InstallationDate) + 10 < year(getdate()) then '10 year service passed' 
    when year(InstallationDate) + 10 > year(getdate()) then 'Ten year service due ' + cast(year(InstallationDate) + 10 as varchar)
    end as '10 Year Service'

    
from equipment e    

order by
case WHEN DATEFROMPARTS(year(getdate()),month(InstallationDate),day(InstallationDate)) < getdate()
    then dateadd(year,1, DATEFROMPARTS(year(getdate()),month(InstallationDate),day(InstallationDate)) )
    else   DATEFROMPARTS(year(getdate()),month(InstallationDate),day(InstallationDate))
    end asc

Ce que je dois faire est de renvoyer une liste de matériel deux mois avant la date de révision.

Pour simplifier, supposons que j'ai ces dates d'installation et qu'elles ont toutes un intervalle d'entretien de 1, ce qui signifie qu'un entretien annuel est requis.

2008-1-17
2011-4-28
2012-5-13
2020-9-6
2006-12-2

Je dois revenir de cette liste à ceux qui (sans tenir compte de l'année) ont une date et un mois qui tombent dans les deux prochains mois. Ainsi, le premier et le dernier élément nécessitent un entretien. Le premier article doit être réparé en janvier et le dernier en décembre.

Je ne suis pas sûr de la meilleure façon d'aborder ce problème. Bien sûr, cela doit être une exigence courante, mais je ne trouve pas d'exemples à tirer. Je peux facilement trouver des dates entre les plages mais j'ai du mal à trouver celle-ci.

Quelqu'un peut-il me diriger dans la bonne direction s'il vous plaît?

Mise à jour: 15/11/2020

Après avoir réfléchi et joué avec les suggestions que d'autres ont faites, j'ai trouvé le script suivant. J'ai réalisé que la plupart de ces équipements sont des extincteurs et que ceux-ci doivent être entretenus chaque année. Ils ont également besoin de services étendus tous les 5 et 10 ans. J'ai besoin d'une liste d'actifs à venir pour l'un de ces services.

CREATE TABLE Equipment(
    Guid uniqueidentifier,
    InstallationDate datetime,
    ServiceInterval tinyint
);


0 commentaires

3 Réponses :


1
votes

La requête suivante devrait fonctionner compte tenu des exigences

SELECT
  InstallationDate,
  CONCAT(MONTH(InstallationDate),'-',DAY(InstallationDate)) as install_mmdd,
  CONCAT(MONTH(DATEADD(MONTH,2,InstallationDate)),'-',DAY(DATEADD(MONTH,2,InstallationDate))) as next_svc_mmdd
    FROM Equipment
    WHERE MONTH(DATEADD(MONTH,2,InstallationDate)) <= 3

Lien SQL Fiddle


1 commentaires

Merci très utile et le violon est d'une grande aide. Merci de répondre. J'ai signalé la réponse précédente comme étant la réponse uniquement parce qu'elle est arrivée en premier.



0
votes

Hmmm. . . Je pense construire la prochaine date d'installation et ensuite simplement faire une comparaison simple:

select e.*
from equipment e cross apply
     (values (case when month(installationdate) < month(getdate()) or
                        (month(installationdate) = month(getdate()) and
                         day(installationdate < day(getdate())
                        )
                   then datefromparts(year(getdate()) + 1, month(installationdate), day(installationdate))
                   else datefromparts(year(getdate()), month(installationdate), day(installationdate))
               end)
     ) v(next_installationdate)                   
where next_installationdate < dateadd(month, -2, getdate())


1 commentaires

Cela a plusieurs erreurs de syntaxe que j'ai corrigées, mais il ne renvoie aucune donnée. Mais merci pour le partage.



1
votes

La fenêtre de dates de deux mois à venir pourrait être calculée en utilisant GETDATE comme CURR_START_DT et EOMONTH (GETDATE (), 2) comme CURR_END_DT. La fenêtre de date à partir d'aujourd'hui est CURR_START_DT = '2020-11-13' et CURR_END_DT = '2021-01-31'. Étant donné que l'année n'a pas d'importance et que la fenêtre de dates peut s'étendre sur plus d'un an, le CALC_DT est créé à l'aide de l'ANNÉE du CURR_START_DT et le PLUS_CALC_DT est créé en utilisant l'ANNÉE du CURR_END_DT. Quelque chose comme ça

Déclarer la table et la requête

InstallationDate    calc_dt     plus_calc_dt    curr_start_dt   curr_end_dt
2008-01-17          2020-01-17  2021-01-17      2020-11-13      2021-01-31
2006-12-02          2020-12-02  2021-12-02      2020-11-13      2021-01-31

Production

declare @YourTable              table(InstallationDate      date);  

insert into @YourTable values 
 ('2008-1-17')
,('2011-4-28')
,('2012-5-13')
,('2020-9-6')
,('2006-12-2');

select yt.InstallationDate, dfp.calc_dt, dfp_plus.calc_dt as plus_calc_dt, 
       dfp.dt as curr_start_dt, dfp.eom as curr_end_dt 
from @YourTable yt
     cross apply
     (select cast(getdate() as date) dt, eomonth(getdate(), 2) eom,
             datefromparts(year(getdate()),
                           month(yt.InstallationDate), 
                           day(yt.InstallationDate)) calc_dt) dfp
     cross apply
     (select datefromparts(year(dfp.eom),
                           month(yt.InstallationDate), 
                           day(yt.InstallationDate)) calc_dt) dfp_plus
where dfp.calc_dt between dfp.dt and dfp.eom
      or
      dfp_plus.calc_dt between dfp.dt and dfp.eom;


1 commentaires

Vraiment bien merci. Je marquerai ceci comme la réponse puisqu'elle est arrivée en premier.