Ordonnancement random

J'ai le tableau suivant dans ma database:

tbl1
PK
Identité du client
ScheduleDay
Time1Start
Time1Stop
Time2Start
Time2Stop
Time3Start
Time3Stop
Statut

Voici quelques exemples de données

ID ClientID ScheduleDay Time1Start Time1Stop Time2Start Time2Stop Time3Start Time3Stop -- -------- ----------- ---------- --------- ---------- --------- ---------- --------- 1 3 Sunday 0000 0800 1000 1300 NULL NULL 2 3 Monday 0000 2359 NULL NULL NULL NULL 3 3 Tuesday 1000 1200 1330 1700 1900 2200 4 3 Wednesday 0000 0800 NULL NULL NULL NULL 5 3 Thursday 0800 1200 NULL NULL NULL NULL 6 3 Friday 0400 0800 0900 1600 NULL NULL 

Les champs Heure sont CHAR (4) car je stocke l'heure dans un format militaire.

Ce que j'ai besoin d'accomplir est ceci; Pour un ID client donné, insérez un ou plusieurs loggings dans une table de planification avec la valeur de time de l'logging dans les timeouts de tbl1. Par exemple, en programmant ClientID 3 le mardi, l'heure prévue pourrait être 1120.

Dans le cas où plusieurs loggings doivent être insérés, les heures programmées ne doivent pas être inférieures à une heure.

Toute aide est appréciée!

Voici ma meilleure estimation de ce que vous essayez de faire. Les deux premières parties du CTE sont vraiment juste pour mettre les choses dans une forme similaire à ce que suggère FlyingStreudel. Idéalement, vous devriez changer la database pour qu'elle corresponde à ce format plutôt que de le faire par le biais des CTE. Cela rendra cela beaucoup plus simple et sera également meilleur pour l'intégrité des données.

Ensuite, je viens d'get les heures de départ distinctes par incréments d'une heure. Vous pouvez le faire en vous joignant à une table Numbers si vous ne pouvez pas utiliser de CTE (vous n'avez pas mentionné la version de SQL Server que vous utilisez).

Enfin, je prends l'une de ces heures de départ au hasard, en utilisant la fonction RAND et ROW_NUMBER. Vous voulez définir une bonne valeur de départ pour RAND ().

 ;WITH TimesAsTimes AS ( SELECT ScheduleDay, CAST(SUBSTRING(T1.Time1Start, 1, 2) + ':' + SUBSTRING(T1.Time1Start, 3, 2) AS TIME) AS time_start, CAST(SUBSTRING(T1.Time1Stop, 1, 2) + ':' + SUBSTRING(T1.Time1Stop, 3, 2) AS TIME) AS time_stop FROM tbl1 T1 WHERE T1.Time1Start IS NOT NULL UNION ALL SELECT ScheduleDay, CAST(SUBSTRING(T2.Time2Start, 1, 2) + ':' + SUBSTRING(T2.Time2Start, 3, 2) AS TIME) AS time_start, CAST(SUBSTRING(T2.Time2Stop, 1, 2) + ':' + SUBSTRING(T2.Time2Stop, 3, 2) AS TIME) AS time_stop FROM tbl1 T2 WHERE T2.Time2Start IS NOT NULL UNION ALL SELECT ScheduleDay, CAST(SUBSTRING(T3.Time3Start, 1, 2) + ':' + SUBSTRING(T3.Time3Start, 3, 2) AS TIME) AS time_start, CAST(SUBSTRING(T3.Time3Stop, 1, 2) + ':' + SUBSTRING(T3.Time3Stop, 3, 2) AS TIME) AS time_stop FROM tbl1 T3 WHERE T3.Time3Start IS NOT NULL ), PossibleTimeStarts AS ( SELECT ScheduleDay, time_start, time_stop FROM TimesAsTimes TAT UNION ALL SELECT ScheduleDay, DATEADD(hh, 1, time_start) AS time_start, time_stop FROM PossibleTimeStarts PTS WHERE DATEADD(hh, 1, time_start) <= DATEADD(hh, -1, PTS.time_stop) ), PossibleTimesWithRowNums AS ( SELECT ScheduleDay, time_start, ROW_NUMBER() OVER(PARTITION BY ScheduleDay ORDER BY ScheduleDay, time_start) AS row_num, COUNT(*) OVER(PARTITION BY ScheduleDay) AS num_rows FROM PossibleTimeStarts ) SELECT * FROM PossibleTimesWithRowNums WHERE row_num = FLOOR(RAND() * num_rows) + 1 

Tout d'abord, vous pouvez essayer un schéma comme

 tbl_sched_avail PK id INT FK client_id INT day INT (1-7) avail_start varchar(4) avail_end varchar(4) 

De cette façon, vous n'êtes pas limité à un nombre fini de clôtures de time.

En ce qui concerne la vérification de la disponibilité des horaires –

 CREATE PROCEDURE sp_ins_sched @start_time varchar(4), @end_time varchar(4), @client_id INT, @day INT AS BEGIN DECLARE @can_create BIT SET @can_create = 0 DECLARE @fence_start INT DECLARE @fence_end INT --IS DESIRED TIME WITHIN FENCE FOR CLIENT DECLARE c CURSOR FOR SELECT avail_start, avail_end FROM tbl_sched_avail WHERE client_id = @client_id AND day = @day OPEN c FETCH NEXT FROM c INTO @fence_start, @fence_end WHILE @@FETCH_STATUS = 0 AND @can_create = 0 BEGIN IF @start_time >= @fence_start AND @start_time < @fence_end AND @end_time > @fence_start AND <= @fence_end SET @can_create = 1 FETCH NEXT FROM c INTO @fence_start, @fence_end END CLOSE c DEALLOCATE c IF @can_create = 1 BEGIN --insert your schedule here END END 

En ce qui concerne le code pour insert réellement l'logging, je devrais en savoir plus sur les tables de la database.