2010-07-19 7 views
2

J'ai le tableau suivant dans ma base de données:Planification aléatoire

tbl1
PK
clientId
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 sont temps CHAR (4) depuis que je suis stocker le temps dans un format militaire.

Ce que j'ai besoin d'accomplir est ceci: Pour un ID client donné, insérez un ou plusieurs enregistrements dans une table de planification avec la valeur de temps de l'enregistrement dans les délais de tbl1. Par exemple, en programmant ClientID 3 le mardi, l'heure programmée peut être 1120.

Si plusieurs enregistrements doivent être insérés, les heures planifiées ne doivent pas être inférieures à une heure.

Toute aide est appréciée!

+0

Quelles sont les entrées connues? C'est-à-dire que le ClientId sait quand la requête est exécutée, le ScheduleDay est-il connu? Le temps devrait-il exister seulement dans la première paire de temps ou dans l'une des paires de temps? Comment aléatoire doit-il être? Par exemple, y a-t-il une raison pour laquelle vous ne pouvez pas simplement ajouter une heure à l'heure de début? – Thomas

+0

Au lieu de donner un exemple de ce que l'heure programmée pourrait être, il serait plus utile si vous fournissiez exactement le jeu de résultats que vous cherchez à obtenir. Sinon, c'est très difficile de vous aider. –

+0

Thomas, Le clientID et ScheduleDay sont connus lorsque la requête est exécutée. Le temps peut être de n'importe quelle paire de temps, et mes exigences exigent qu'il soit assez aléatoire pour que ce soit imprévisible. Tom H, Les résultats de la requête seraient le ClientID et une heure qui tombe dans l'une des paires de fois pour le jour fourni à la requête. – DoubleJ92

Répondre

1

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 base de données 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'obtenir les heures de début distinctes en incréments d'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 
+0

J'utilise SQL Server 2008 – DoubleJ92

+0

Ensuite, ce qui précède devrait fonctionner pour vous, compte tenu des mises en garde que j'ai mentionnées (amorcer correctement RAND(), et il serait mieux s'il est possible de reconcevoir la DB au lieu d'utiliser les deux premiers CTE) –

+0

Cela l'a fait pour moi. Merci! – DoubleJ92

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 temps.

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 insérer réellement l'enregistrement je besoin de savoir plus sur les tables de la base de données.