Tout le problème c'est que personne ici n'arrive à y voir clair dans votre demande.
Comme déjà répété par plusieurs personnes, vous exposez un jeu d'essai avec plusieurs lignes par client mais sans que nous ne puissions déterminer l'ordonnancement de ces lignes (aucun critère visible ne le permet)
Ensuite vous parlez d'une fonction qui permet de récupérer le solde, très bien... mais dans ce cas cas, autant ajouter une colonne "Solde Initial" dans vote jeu d'essai qui simulera le résultat de cette fameuse fonction
Pour finir, le mieux serait d'exposer un minimum de code pour avancer dans votre problématique
Tout simplement un début d'algo :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28 DECLARE CURSOR C_test IS select AGENCE,CLIENT,MONTANT_ASSURANCE,COMMISSION,SOLDE_CLIENT, LAG(Client) OVER(PARTITION BY Agence ORDER BY Agence, Client) AS LAST_Client from Ma_table order by COMMISSION asc; Solde_Initial NUMBER(17,4) := 0; Solde_Actuel NUMBER(17,4) := 0; BEGIN FOR i IN C_test LOOP -- Récupération du solde initial à la première occurrence d'un client IF (i.LAST_Client IS NULL OR i.LAST_Client <> i.Client) THEN Solde_Initial := FCT_Solde_Initial; Solde_Actuel := Solde_Initial; END IF; Solde_Actuel := i.Solde_Actuel - i.Commission; UPDATE ... [..] END LOOP; END; /
Croyez-moi, tout le monde y verra plus clair et pourra mieux vous aider car le besoin ne m'a pas l'air si complexe par contre la façon de l'exposer est très laborieuse
DBA Oracle
Rédacteur du blog : dbaoraclesql.canalblog.com
merci pour votre retour,
ici je n'ai pas besoin de faire un UPDATE du tout, je veux juste afficher !!
j'ai réexpliquer plusieurs fois je ne sais pas ou il est le problème !!
je vais illustrer par un exemple avant et après :
1- je fais un select depuis une VUE ou un TABLEAU
2- le résultat et sous forme :
AGENCE ,CLIENT, MONTANT_ASSURANCE, COMMISSION, SOLDE_CLIENT
3- exemple de données :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10 AGENCE ,CLIENT, MONTANT_ASSURANCE, COMMISSION, SOLDE_CLIENT A1 001 200 5 150 SOLDE INITIAL DU CLIENT 001 = 150 A1 001 250 10 - A1 001 300 15 - ------- A1 002 150 5 500 SOLDE INITIAL DU CLIENT 002 = 500 A1 002 300 10 - ------- A1 003 300 15 10 SOLDE INITIAL DU CLIENT 003 = 10
ici on aura jamais besoin de la colonne MONTANT_ASSURANCE on travaille uniquement avec SOLDE_CLIENT et commission .
remarque : les commissions doivent être par ordre croissant par client
4- on commence le traitement :
pour le client 001 :
solde initial = 150 : commission 01 = 5
ici dans la ligne 02 du client 001 on doit trouver (150-5) comme SOLDE = 145
solde initial devient = 145 : commission 02 = 10
ici dans la ligne 03 du client 001 on doit trouver (145-10) comme SOLDE = 135
pour le client 002 :
solde initial = 500 : commission 01 = 5
ici dans la ligne 02 du client 001 on doit trouver (500-5) comme SOLDE = 450
pour le client 003 :
solde initial = 10 : commission 01 = 15
ici il y a pas de deuxième ligne donc on fait rien !!
en grosso-modo en fait le traitement si il y'a plus de 1 ligne pour un client donnée
suis-je clair maintenant?
Cela pourrait donner quelque chose comme ça en PL/SQL
Y a sûrement moyen de simplifier, disons que c'est un premier jet
A tester, ça m'étonnerait que cela fonctionne du premier coup
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37 DECLARE CURSOR C_test IS select AGENCE,CLIENT,MONTANT_ASSURANCE,COMMISSION,SOLDE_CLIENT, LAG(Client) OVER(PARTITION BY Agence ORDER BY Agence, Client) AS LAST_Client, LEAD(Client) OVER(PARTITION BY Agence ORDER BY Agence, Client) AS NEXT_Client LAG(COMMISSION) OVER(PARTITION BY Agence,Client ORDER BY Agence, Client) AS LAST_Comm, from Ma_table order by COMMISSION asc; Solde_Initial NUMBER(17,4) := 0; Solde_Actuel NUMBER(17,4) := 0; BEGIN dbms_output.put_line('AGENCE;CLIENT;MONTANT_ASSURANCE;COMMISSION;Solde_Actuel'); FOR i IN C_test LOOP -- Récupération du solde initial à la première occurrence d'un client IF (i.LAST_Client IS NULL OR i.LAST_Client <> i.Client) THEN Solde_Actuel := i.SOLDE_CLIENT; -- Calcul uniquement si le client a plus d'une ligne IF (i.NEXT_Client IS NOT NULL AND i.LAST_Client <> i.Client) THEN L_Calcul := TRUE; ELSE L_Calcul := FALSE; END IF; END IF; IF (L_Calcul) THEN Solde_Actuel := Solde_Actuel - NVL(i.LAST_Comm,0); END IF; dbms_output.put_line(i.AGENCE||';'||i.CLIENT||';'||i.MONTANT_ASSURANCE||';'||i.COMMISSION||';'||Solde_Actuel); END LOOP; END; /
Scriuiw je tiens a vous remercier, ça fonctionne à merveille.
merci aux membre qui ont participé à cette discussion.
Pas besoin de curseur ici, une requête récursive fait le travail.
Données
Requête
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 create table Mytable ( AGENCE varchar2(2) not null , CLIENT varchar2(3) not null , MONTANT_ASSURANCE number(3) not null , COMMISSION number(5,2) not null , SOLDE_CLIENT number(3) null ); insert into Mytable (AGENCE, CLIENT, MONTANT_ASSURANCE, COMMISSION, SOLDE_CLIENT) select 'A1', '001', 200, 5, 150 from dual union all select 'A1', '001', 250, 10, null from dual union all select 'A1', '001', 300, 15, null from dual union all select 'A1', '002', 150, 5, 500 from dual union all select 'A1', '002', 300, 10, null from dual union all select 'A1', '003', 300, 15, 10 from dual; commit;
Résultat
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23 with cte_mytable_rn (AGENCE, CLIENT, MONTANT_ASSURANCE, COMMISSION, SOLDE_CLIENT, rn) as ( select AGENCE, CLIENT, MONTANT_ASSURANCE, COMMISSION, SOLDE_CLIENT , row_number() over(partition by AGENCE, CLIENT order by COMMISSION asc) from MyTable ) , cte_recurs (AGENCE, CLIENT, MONTANT_ASSURANCE, COMMISSION, SOLDE_CLIENT, rn) as ( select AGENCE, CLIENT, MONTANT_ASSURANCE, COMMISSION, SOLDE_CLIENT, rn from cte_mytable_rn where rn = 1 union all select cte.AGENCE, cte.CLIENT, tbl.MONTANT_ASSURANCE, tbl.COMMISSION , cte.SOLDE_CLIENT - cte.COMMISSION , tbl.rn from cte_recurs cte join cte_mytable_rn tbl on tbl.AGENCE = cte.AGENCE and tbl.CLIENT = cte.CLIENT and tbl.rn = cte.rn + 1 ) select AGENCE, CLIENT, MONTANT_ASSURANCE, COMMISSION, SOLDE_CLIENT from cte_recurs order by AGENCE, CLIENT, COMMISSION;
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8 AGENCE CLIENT MONTANT_ASSURANCE COMMISSION SOLDE_CLIENT ------ ------ ----------------- ---------- ------------ A1 001 200 5 150 A1 001 250 10 145 A1 001 300 15 135 A1 002 150 5 500 A1 002 300 10 495 A1 003 300 15 10
Email : http://scr.im/waldar
Waldar Deux mots : Tu gères
meilleure solution merci infiniment.
TOP DU TOP
Vous avez un bloqueur de publicités installé.
Le Club Developpez.com n'affiche que des publicités IT, discrètes et non intrusives.
Afin que nous puissions continuer à vous fournir gratuitement du contenu de qualité, merci de nous soutenir en désactivant votre bloqueur de publicités sur Developpez.com.
Partager