C'est vrai que l'examun ligne à ligne n'est pas une bonne idée, je vais vous énoncé la globalité de ce que je dois faire, j'ai UNE seule erreure (une ligne qui se fusionne à une autre alors qu'elle ne devrait pas) donc peut être que vous pourrez m'aider.
J'ai une table, ph2_item avec ses colonnes
Order_id, customer_id, item_id, order_date,ship_date, old_sys_ref (l'ancien order_id)
Je dois :
- Redonner des order_id pour les insérer dans une autre table du même type.
- Les order_id doivent être donné par ordre des order_date.
- Certains customer (qui se trouvent identifié dans une vue que j'ai créé) ont plus d'un magasin, donc parfois il arrive qu'il y est des commandé avec la même ship_date, le même order_date, le même customer_id, et pas le même order_id, donc je dois fusionner ces lignes pour qu'elles naient plus qu'un seul order_id
- Une fois ceci fait, on se retrouver avec un order_id (exemple 635) qui possede plusieurs fois le même item_id (1), il faut donc changer ça.
Voilà comment j'ai procédé (mais c'est pas encore juste)
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 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53
| declare
cursor c_ph2_item IS SELECT * FROM ph2_item where customer_id in (select customer_id from multisite where numbersite>1) ORDER BY customer_id,order_id,item_id,ship_date for update of order_id;
teston ph2_item.customer_id%type;
previousline c_ph2_item%rowtype;
max_order sales_order.order_id%type;
begin
SELECT max(order_id) INTO max_order FROM sales_order;
UPDATE ph2_item p3
SET order_id= (SELECT orders FROM (
SELECT dense_rank() over(ORDER BY order_date,ship_date,customer_id) orders, old_sys_ref
FROM ph2_item )p2 WHERE p3.old_sys_ref=p2.old_sys_ref
);
update ph2_item
set order_id= order_id+ max_order;
open c_ph2_item;
fetch c_ph2_item into previousline;
close c_PH2_item;
for enreg in c_ph2_item loop
if (enreg.ship_date= previousline.ship_date)
and (enreg.customer_id= previousline.customer_id)
and (enreg.order_date= previousline.order_date)
and (previousline.order_id=enreg.order_id)
and (previousline.old_sys_ref<>enreg.old_sys_ref)
and ((previousline.item_id=enreg.item_id) or (previousline.item_id>enreg.item_id)) then
update ph2_item set item_id= previousline.item_id+1
where current of c_ph2_item;
previousline.item_id:=previousline.item_id+1;
else previousline.item_id:=enreg.item_id;
end if;
previousline.ship_date:=enreg.ship_date;
previousline.customer_id:=enreg.customer_id;
previousline.order_date:=enreg.order_date;
previousline.order_id:=enreg.order_id;
previousline.old_sys_ref:=enreg.old_sys_ref;
end loop;
end; |
En gros je fais ça en plusieur étapes :
1- Grâce à la fonction dense_rank je trie les lignes par order_date,ship_date,customer_id, donc si des lignes ont ces 3 choses = elles obtiennent le même order_id.
2- Ensuite je remplace ce résultat par le max de la table cible + leur rang ...
3- J'ouvre le curseur pour ouvrir la première ligne (le curseur est fait de telle façon qu'il ne conserve que les lignes des clients multisite)
4- Je vérifie si les lignes sont les même, auquel cas je modifie juste l'item_id.
Voilà ... Le premier problème et la fonction dense_rank qui est assez longue à lancer (30 secondes) et qui visiblement fait 1 erreur puisque lorsque je fais
Select count (distinct order_id) from ph2_item
j'obtien 1850 ... au lieu de 1851 !
Partager