3 idées > 1 solution avec les requêtes
J'espérais une autre réponse de votre part Mr Brouard mais j'avoue que vous m'avez déjà bien aidé, cela fait un an que j'ai commencé à me pencher sur le TSQL et vos articles tout comme votre livre que j'ai acheté m'ont bien servi.
1ère idée :
En effet il semble bien que les curseurs soient une solution puisqu'il agissent ligne par ligne et que dans le cas présent il s'agirait de classer par ordre chronologie puis de vérifier la ligne précédente afin de pouvoir déterminer un élément commun et ainsi pouvoir agréger les lignes ensemble. Cependant je ne sais pas utiliser les curseurs mais j'apprendrai quand j'aurai du temps.
2ème idée :
Utiliser la récursivité avec les CTE, mais là aussi je ne sais pas comment faire, en gros cela reviendrait à faire la chose suivante mais en boucle jusqu'à ce qu'on ait identifié toutes les lignes :
WITH TMP1 AS (select 'KAR' as Ste, 20012 as Mat, 39040 as Du,39100 as Au
union select 'KAR' as Ste, 20012 as Mat, 39101 as Du,39130 as Au
union select 'KAR' as Ste, 20012 as Mat, 39131 as Du,39150 as Au
union select 'KAR' as Ste, 20012 as Mat, 39151 as Du,39167 as Au
union select 'KAR' as Ste, 20012 as Mat, 39190 as Du,39203 as Au
union select 'KAR' as Ste, 20012 as Mat, 39204 as Du,39223 as Au ),
TMP2 as ( select Ste,Mat,Du,Au ,case when exists(select * from TMP1 as TAB2 where TAB1.Ste=TAB2.Ste and TAB1.Mat=TAB2.Mat and TAB1.Du=TAB2.Au+1 ) then NULL else Du end as Debut FROM TMP1 as TAB1),
TMP3 as ( select Ste,Mat,Du,Au ,case when Debut is null then (select Debut from TMP2 as TAB2 where TAB1.Ste=TAB2.Ste and TAB1.Mat=TAB2.Mat and AB1.Du=TAB2.Au+1 ) else Debut end as Debut FROM TMP2 as TAB1),
TMP4 as ( select Ste,Mat,Du,Au ,case when Debut is null then (select Debut from TMP3 as TAB2 where TAB1.Ste=TAB2.Ste and TAB1.Mat=TAB2.Mat and TAB1.Du=TAB2.Au+1 ) else Debut end as Debut FROM TMP3 as TAB1),
TMP5 as ( select Ste,Mat,Du,Au ,case when Debut is null then (select Debut from TMP4 as TAB2 where TAB1.Ste=TAB2.Ste and TAB1.Mat=TAB2.Mat and TAB1.Du=TAB2.Au+1 ) else Debut end as Debut FROM TMP4 as TAB1)
select * from TMP5
3ème idée et ma solution :
D'abord un exemple :
WITH TMP3 AS ( SELECT 'KAR' AS ENT_ID,'20012' AS SAL_MATR,36876 AS E_S_DATE, 2 AS E_S_TYP, 39256 AS E_S_DATES,'CP' AS MES_IDS
UNION SELECT 'KAR' AS ENT_ID,'20012' AS SAL_MATR,39257 AS E_S_DATE, 3 AS E_S_TYP, 39478 AS E_S_DATES,'CP' AS MES_IDS
UNION SELECT 'KAR' AS ENT_ID,'20012' AS SAL_MATR,39479 AS E_S_DATE, 2 AS E_S_TYP, 39683 AS E_S_DATES,'CP' AS MES_IDS
UNION SELECT 'KAR' AS ENT_ID,'20012' AS SAL_MATR,39684 AS E_S_DATE, 3 AS E_S_TYP, 39700 AS E_S_DATES,'CP' AS MES_IDS
UNION SELECT 'KAR' AS ENT_ID,'20012' AS SAL_MATR,39701 AS E_S_DATE, 1 AS E_S_TYP, 39750 AS E_S_DATES,'DEM' AS MES_IDS
UNION SELECT 'KAR' AS ENT_ID,'20012' AS SAL_MATR,39765 AS E_S_DATE, 1 AS E_S_TYP, 39810 AS E_S_DATES,'DEM' AS MES_IDS
UNION SELECT 'KAR' AS ENT_ID,'20012' AS SAL_MATR,39850 AS E_S_DATE, 2 AS E_S_TYP, 39900 AS E_S_DATES,'CP' AS MES_IDS
UNION SELECT 'KAR' AS ENT_ID,'20012' AS SAL_MATR,39901 AS E_S_DATE, 3 AS E_S_TYP, 42367 AS E_S_DATES,'CP' AS MES_IDS ),
TMP4 AS ( SELECT ENT_ID,SAL_MATR,E_S_DATE,E_S_TYP,E_S_DATES,MES_IDS
,CASE WHEN NOT EXISTS (SELECT * FROM TMP3 AS TAB2 WHERE TAB2.ENT_ID=TAB1.ENT_ID AND TAB2.SAL_MATR=TAB1.SAL_MATR AND TAB2.E_S_DATES+1=TAB1.E_S_DATE) THEN E_S_DATE ELSE NULL END AS Debut
,CASE WHEN NOT EXISTS (SELECT * FROM TMP3 AS TAB2 WHERE TAB2.ENT_ID=TAB1.ENT_ID AND TAB2.SAL_MATR=TAB1.SAL_MATR AND TAB2.E_S_DATE-1=TAB1.E_S_DATES) THEN E_S_DATES ELSE NULL END AS Fin
FROM TMP3 AS TAB1 )
SELECT ENT_ID,SAL_MATR,E_S_DATE,E_S_TYP,E_S_DATES,MES_IDS
,CASE WHEN Debut IS NULL THEN (SELECT MAX(Debut) FROM TMP4 AS TAB2 WHERE Debut IS NOT NULL AND TAB2.ENT_ID=TAB1.ENT_ID AND TAB2.SAL_MATR=TAB1.SAL_MATR AND TAB2.Debut<TAB1.Fin GROUP BY ENT_ID,SAL_MATR) ELSE Debut END AS Debut , Fin
FROM TMP4 AS TAB1 WHERE Fin IS NOT NULL
L'idée est la suivante. Je n'ai finalement pas besoin des lignes intermédiaires qui se trouvent à l'intérieur de la période, donc je vais marquer uniquement la première et la dernière ligne du sous ensemble avec l'élément connu, c'est à dire pour la première ligne la date de début et pour la dernière ligne la date de fin. Puis dans une requête suivante je ne retiens que les dernières lignes auxquelles je vais ajouter s'il n'existe pas la valeur du début (s'il n'y a qu'une ligne le début et la fin sont connus de suite), celle ci correspondant à la valeur maximum du Début pour les lignes qui ont une date de début inférieur à la date de fin de ma ligne actuelle.
Ce n'est peut être pas très clair mais en décortiquant le code vous devriez comprendre.
Si vous quelqu'un a une autre idée, je suis preneur.
deux à trois solutions...
Bonjour,
J'ai plusieurs solutions pour ton problème.
Une dernière question pour t'envoyer ma réponse :
est ce que les deux champs E_S_DATE et E_S_DATES sont uniques ou risquent d'avoir des doublons. S'ils sont uniques, j'ai trois solutions. Sinon, j'en ai deux. Dans tous les cas, tu apprendras avec les curseurs ;)