Aide problème sous SQL Urgent

BOB2015 - 26 déc. 2012 à 09:55
cs_Malkuth Messages postés 268 Date d'inscription samedi 22 février 2003 Statut Membre Dernière intervention 24 avril 2013 - 1 janv. 2013 à 16:02
Bonjour à vous forum,

J'ai la table table source suivante dans une base SQL.

CODE R LIB CODES ASSO FORMULA
R001 XXX A02;A03;A04;A05 +CA*CHG*1-TX
R002 YYY A02;A03;A04;A05 +CA*CHG*1-TOTO
R003 ZZZ A07 +CHG*1-TOTO
R004 UUU A10 +CHG*1-TOTO



Mais j'aimerais en sortie le résultat suivant :

CODE R LIB CODES ASSO FORMULA
R001 XXX A02 +CA*CHG*1-TX
R001 XXX A03 +CA*CHG*1-TX
R001 XXX A04 +CA*CHG*1-TX
R001 XXX A05 +CA*CHG*1-TX
R002 YYY A02 +CA*CHG*1-TOTO
R002 YYY A03 +CA*CHG*1-TOTO
R002 YYY A04 +CA*CHG*1-TOTO
R002 YYY A05 +CA*CHG*1-TOTO
R003 ZZZ A07 +CHG*1-TOTO
R004 UUU A10 +CHG*1-TOTO

Mais je ne vois pas trop comment récupérer les valeurs de cellules en ligne.

Sur la première ligne par exemple le CODES ASSO est égal à A02 ; A03 ; A04 ; A05 et je dois récupérer autant des lignes qu'il y a des codes et bien évidement les associer avec la colonne CODE R.

Il faut que cela soit absolument fait en SQL, connaissez vous une fonction qui pourrait m?aider à récupérer les CODES ASSO qui sont séparés par « ; » et ensuite les récupérer en ligne ? Comment expliqué dans l'exemple précédent ?

D'avance je vous remercie,

2 réponses

yann_lo_san Messages postés 1137 Date d'inscription lundi 17 novembre 2003 Statut Membre Dernière intervention 23 janvier 2016 26
26 déc. 2012 à 17:05
Salut,

tout d'abord, je dois dire qu'il y a un défaut de conception dans ton exemple car le champ code_asso ne devrait pas exister dans une conception relationnelle. A la place, il devrait y avoir une table de relation 1,n contenant le code_r (unique) et le code asso, avec autant de ligne que de code asso.
Grâce à cela une seule jointure te renverrai le résultat voulu.

Ceci étant dit et si tu ne peux pas changer la conception de ta BDD, il faut tout d'abord créer une "fonction table", c'est à dire une fonction qui renvoi une table "en ligne" locale.
Voici un exemple de fonction table SPLIT :

CREATE FUNCTION dbo.SPLIT
(
@string varchar(8000),  /* la chaine a splitter*/
@delimiter char(1),   /* le delimiteur */
@useEmptyValue bit    /* autorise 2 délimiteurs qui se suivent */
)        
RETURNS @temptable TABLE(items varchar(8000))        
AS        
BEGIN        
    IF isnull(@string,'')='' or isnull(@delimiter,'')='' RETURN;
    DECLARE @idx int, @substring varchar(8000)
    SET @idx = 1
    WHILE @idx != 0
    BEGIN
        SET @idx = charindex(@delimiter, @string)
        IF @idx > 0
            SET @substring = left(@string, @idx - 1)
        ELSE        
            SET @substring = @string

        IF len(@substring) > 0 or isnull(@useEmptyValue,0) = 1
            INSERT INTO @temptable(Items) VALUES(@substring);

        SET @string = right(@string, len(@string)-@idx)
        IF len(@string) = 0
BREAK;
    END
RETURN;
END


Ensuite, il faut "boucler" sur chaques lignes et passer par une table de travail pour remplir autant de ligne que de codes asso, ici avec un curseur et des tables locales pour test :

/* table exemple */
DECLARE @tbl table
(
_code_r varchar(4),
_lib varchar(35),
_codeasso varchar(50),
_formula varchar(35)
);
/* datas exemple */
INSERT INTO @tbl VALUES('R001', 'XXX', 'A02;A03;A04;A05', '+CA*CHG*1-TX ');
INSERT INTO @tbl VALUES('R002', 'YYY', 'A02;A03;A04;A05', '+CA*CHG*1-TOTO ');
INSERT INTO @tbl VALUES('R003', 'ZZZ', 'A07', '+CHG*1-TOTO ');
INSERT INTO @tbl VALUES('R004', 'UUU', 'A10', '+CHG*1-TOTO');

/* table résultat */
DECLARE @tblRes table
(
_code_r varchar(4),
_lib varchar(35),
_codeasso varchar(4),
_formula varchar(35)
);

/* curseur sur chaques lignes à traiter */
DECLARE @codeTemp varchar(4), @codeAsso varchar(50)
DECLARE myCursor CURSOR LOCAL FORWARD_ONLY FOR SELECT _code_r, _codeasso FROM @tbl
OPEN myCursor
FETCH NEXT FROM myCursor INTO @codeTemp, @codeAsso
WHILE @@FETCH_STATUS=0
BEGIN
/* Rempli et duplique les lignes si plusieurs code asso */
INSERT INTO @tblRes(_code_r, _lib, _codeasso, _formula)
SELECT 
@codeTemp, 
_lib, 
ref.items,
_formula
FROM @tbl, (SELECT items FROM dbo.SPLIT(@codeAsso, ';', 1)) ref
WHERE _code_r = @codeTemp

FETCH NEXT FROM myCursor INTO @codeTemp, @codeAsso
END
CLOSE myCursor
DEALLOCATE myCursor

/* le résultat */
SELECT * from @tblRes ORDER BY _code_r


bye...
0
cs_Malkuth Messages postés 268 Date d'inscription samedi 22 février 2003 Statut Membre Dernière intervention 24 avril 2013 4
1 janv. 2013 à 16:02
j'aime pas trop le bouclage avec curseur, je lui prefaire un CROSS APPLY :

on garde la fonction SPLIT précédente.


SELECT 
    [SRC].[CODE R],
    [SRC].[LIB],
    [CODES_TBL].[items] AS [CODE ASSO],
    [SRC].FORMULA
FROM [SRC]
CROSS APPLY dbo.SPLIT([SRC].[CODES ASSO], ';', 1) AS [CODES_TBL]
0
Rejoignez-nous