SQL Server génère des données à l'aide de certaines données de la table

Supposons que nous ayons une table dans SQL Server qui stocke les décalages pour les médecins, donc au lieu de stocker des dates explicites que nous utilisons en semaine, la table ressemble à ceci

ShiftId Day DoctorId FromTime ToTime -------------------------------------------------- 1 SUN 1 08:00:00 16:00:00 2 MON 1 09:00:00.00 14:00:00 3 TUE 1 09:00:00.00 15:00:00 4 WED 1 10:00:00.00 17:00:00 5 THU 1 13:00:00.00 18:00:00 

Je veux créer une instruction select pour générer des dates explicites en utilisant datatables stockées dans cette table

Exemple

supposons que je veux générer des dates entre le Sunday 19th February 2017 au Tuesday 28th February 2017 , la sortie devrait être comme ça

 DoctorId Date Day FromTime ToTime ------------------------------------------------------------ 1 '02-19-2017' SUN 08:00:00 16:00:00 1 '02-20-2017' MON 09:00:00 14:00:00 1 '02-21-2017' TUE 09:00:00 15:00:00 1 '02-22-2017' WED 10:00:00 17:00:00 1 '02-23-2017' THU 13:00:00 18:00:00 1 '02-26-2017' SUN 08:00:00 16:00:00 1 '02-27-2017' MON 09:00:00 14:00:00 1 '02-28-2017' TUE 09:00:00 15:00:00 

Explication

Les heures générées pour ces dates correspondent aux jours stockés dans notre table par exemple l'heure générée pour '02-19-2017' dans la première rangée est 08:00:00 16:00:00 parce que '02-19-2017' est dimanche , et l'heure générée pour '02-20-2017' dans la deuxième rangée est 09:00:00 14:00:00 parce que '02-20-2017' est lundi et ainsi de suite.

Comme vous pouvez remarquer aucune date pour le 24th February FRI et le 25th February SAT , parce que nous ne stockons pas Friday et Saturday dans notre table

Pouvons-nous écrire une requête dans T-SQL qui renvoie ce résultat?

J'utiliserais vos parameters d'input From / To pour générer un calendar à la volée dans un CTE récursif, puis le joindre à votre table de décalage en fonction de la valeur du jour de la semaine.

 DECLARE @Shift TABLE (ShiftID INT, [Day] VARCHAR(3), DoctorId INT, FromTime TIME, ToTime TIME) INSERT INTO @Shift VALUES (1,'SUN',1,'08:00:00','16:00:00'), (2,'MON',1,'09:00:00.00','14:00:00'), (3,'TUE',1,'09:00:00.00','15:00:00'), (4,'WED',1,'10:00:00.00','17:00:00'), (5,'THU',1,'13:00:00.00','18:00:00') DECLARE @D1 DATE, @D2 DATE SET @D1 = '2017-02-19' SET @D2 = '2017-02-28' ;WITH Calendar AS ( SELECT @D1 AS [DateVal], LEFT(DATENAME(WEEKDAY,@D1),3) AS [DWName] UNION ALL SELECT DATEADD(DAY,1,DateVal), LEFT(DATENAME(WEEKDAY,DATEADD(DAY,1,DateVal)),3) FROM Calendar WHERE DateVal<@D2 ) SELECT S.DoctorId, C.DateVal, S.[Day], S.FromTime, S.ToTime FROM @Shift S JOIN Calendar C ON S.[Day]=C.DWName 

utiliser un calendar CTE, joindre à celui-ci

 with DateCTE as ( select @DateFrom as Date1 union select dateadd('DD',1,Date1) from DateCTE where Date1 < @DateTo ) select D1.*, datename('DW',Date1) as Day FromTime, ToTime from DateCTE D1 left join MyTable M2 on datename('DW',Date1) like M2.Day where datename('DW',Date1) not like 'Fri%' and datename('DW',Date1) not like 'Sat%' 

Je pense que l'utilisation de SQL pour ce type de tâche est une mauvaise idée en raison de l'utilisation de nombreuses opérations logiques. Utiliser une fonction C # devrait être plus efficace.

Utiliser SQL ou C # serait la même solution logique:

1 – Créez une table temporaire qui conservera votre résultat.

2 – Bouclez votre date de début à la fin. Pour chaque date, prenez la partie JOUR. Depuis la partie JOUR, récupérez votre champ FromTime et ToTime. Insérez le résultat sur votre table temporaire.

3 – Renvoyez la table temporaire (Ou Sélectionnez et détruisez-la).

Vous devriez probablement avoir une table de calendar dans votre database. Pour ce faire, vous pouvez utiliser des CTE récursifs ou une table de nombres à peu près au même effet:

 with n as ( select row_number() over (order by (select null)) - 1 as n from master.spt_values ) select dd.doctorid, d.dte, s.day, s.fromtime, s.totime from (select dateadd(day, nn, @startdate) as dte from n where dateadd(day, nn, @startdate) <= @enddate ) d cross join (select distinct doctorid from shifts ) dd join shifts s on upper(left(datename(wd, d.dte), 3)) = s.day and ss.doctorid = d.doctorid; 

C'est un peu difficile. L'idée est de générer les dates (ce qui est assez facile en utilisant la table des nombres). Ensuite, faites une cross join les médecins, de sorte que tous les médecins ont toutes les dates. Enfin, revenez à la table des shifts pour get les loggings correspondants (le cas échéant) et les heures appropriées.

Notez que cette version fonctionnera pour plusieurs médecins.

Tu peux essayer ça

 DECLARE @STARTDate date = '02-19-2017', @ToDate date = '02-27-2017' ;WITH myCTE AS ( SELECT @STARTDate AS MyDate, 1 AS iID UNION ALL SELECT DATEADD(DAY,1,MyDate), iID + 1 FROM myCTE WHERE MyDate < @ToDate ) SELECT * FROM YourTable JOIN myCTE on myCTE.iID = YourTable.ID