Précédent   Forum des professionnels en informatique > Bases de données > Oracle > PL/SQL
PL/SQL Forum d'entraide sur le PL/SQL
Partagez cette discussion sur d'autres réseaux sociaux : Viadeo Twitter Google Facebook Digg Delicious MySpace Yahoo
Réponse Proposer ce sujet en actualité
 
Outils de la discussion
Publicité
'
Vieux 27/05/2011, 17h04   #1
Membre actif
 
Inscription : mai 2004
Messages : 725
Détails du profil
Informations forums :
Inscription : mai 2004
Messages : 725
Points : 193
Points : 193
Par défaut Comment supprimer un élément d'une loop ?

Bonjour,

J'aimerais pouvoir supprimer la ligne rec (le premier résultat de la boucle)
J'aimerais faire un delete de rec si rec a des champs egaux avec rec2.
Voir le code ci dessous :

Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
 
 
FOR rec IN ( SELECT r.ID_DEMANDE,r.TYPE_EXAMEN, r.DATE_PRESCRIPTION
			          FROM radiologie r
			          WHERE r.ID_EXAMEN LIKE '%*'
  )
  LOOP  
		FOR rec2 IN ( SELECT r.ID_DEMANDE,r.TYPE_EXAMEN, r.DATE_PRESCRIPTION
					FROM radiologie r
		)
		LOOP
 
			IF(rec2.ID_DEMANDE = rec.ID_DEMANDE,SUBSTR(rec.ID_EXAMEN,1,2)
				AND r3.TYPE_EXAMEN = rec.TYPE_EXAMEN
				AND r3.ID_EXAMEN LIKE '%*'
				AND TO_CHAR (r3.DATE_PRESCRIPTION, 'DD/MM/YYYY HH24:mi:ss')= TO_CHAR (rec.DATE_PRESCRIPTION, 'DD/MM/YYYY HH24:mi:ss');)
                        DELETE rec 
 
 
		END LOOP;
 
   END LOOP;
Comme vous le voyez j'aimerais supprimer rec si une condition est remplie. Je ne sais pas comment faire cela en SQL. COmment faire ceci en SQL ou PL :

Code :
1
2
3
4
5
6
 
IF(rec2.ID_DEMANDE = rec.ID_DEMANDE,SUBSTR(rec.ID_EXAMEN,1,2)
				AND r3.TYPE_EXAMEN = rec.TYPE_EXAMEN
				AND r3.ID_EXAMEN LIKE '%*'
				AND TO_CHAR (r3.DATE_PRESCRIPTION, 'DD/MM/YYYY HH24:mi:ss')= TO_CHAR (rec.DATE_PRESCRIPTION, 'DD/MM/YYYY HH24:mi:ss');)
                        DELETE rec

Voici l'algorithme que je tente de reproduire :

Citation:

Pour chaque ligne de la table RADIOLOGIE dont ID_EXAMEN se termine par une étoile
si pour le triplet T1 = [ ID_DEMANDE concaténé avec les 2 premiers caractères de ID_EXAMEN ; TYPE_EXAMEN ; DATE_PRESCRIPTION ]
il existe une ligne de la table RADIOLOGIE dont le triplet T2 = [ ID_DEMANDE ; TYPE_EXAMEN ; DATE_PRESCRIPTION] est égal à T1
alors supprimer la ligne (correspondant à T1, T2 étant une version plus récente du doublon)


Merci
Battosaiii est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 27/05/2011, 17h58   #2
Membre Expert
 
Inscription : août 2008
Messages : 1 271
Détails du profil
Informations forums :
Inscription : août 2008
Messages : 1 271
Points : 1 929
Points : 1 929
Bizarre modèle, déjà il y a des doublons mais je ne comprends pas bien la logique derrière
Citation:
ID_DEMANDE concaténé avec les 2 premiers caractères de ID_EXAMEN
Peut être comme ça, mais pas sûr, pense à rollback ou à te faire une table de backup :
Code :
1
2
3
4
5
6
7
DELETE FROM radiologie r1
 WHERE ID_EXAMEN LIKE '%*'
   AND EXISTS (SELECT 1
                 FROM radiologie r2
                WHERE r2.DATE_PRESCRIPTION = r1.DATE_PRESCRIPTION
                  AND r2.TYPE_EXAMEN = r1.TYPE_EXAMEN
                  AND r2.ID_DEMANDE = r1.ID_DEMANDE||substr(ID_EXAMEN,1,2))
skuatamad est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 31/05/2011, 09h19   #3
Membre actif
 
Inscription : mai 2004
Messages : 725
Détails du profil
Informations forums :
Inscription : mai 2004
Messages : 725
Points : 193
Points : 193
Ca marche ta fonction sur une table avec peu d'éléments.


Par contre la requete prend trop de temps sur une base de 138 000 elements. Il me faut trouver une requete plus rapide.
Battosaiii est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 31/05/2011, 11h54   #4
Membre actif
 
Inscription : mai 2004
Messages : 725
Détails du profil
Informations forums :
Inscription : mai 2004
Messages : 725
Points : 193
Points : 193
Par défaut Comment supprimer rapidement les doublons d'une table avec 150 000 elements ?

Bonjour,

Comment supprimer les doublons de ma table ? Je vais appliquer les conditions de l'algo suivant pour supprimer les doublons de cette table :

Citation:
Pour chaque ligne de la table RADIOLOGIE dont ID_EXAMEN se termine par une étoile
si pour le triplet T1 = [ ID_DEMANDE concaténé avec les 2 premiers caractères de ID_EXAMEN ; TYPE_EXAMEN ; DATE_PRESCRIPTION ]
il existe une ligne de la table RADIOLOGIE dont le triplet T2 = [ ID_DEMANDE ; TYPE_EXAMEN ; DATE_PRESCRIPTION] est égal à T1
alors supprimer la ligne (correspondant à T1, T2 étant une version plus récente du doublon)

Voir la requete sql que j'ai trouvé : http://www.developpez.net/forums/d10...-element-loop/

Malheureusement la requete SQL du lien precedent dure assez longtemps.+ de 10 minutes !!!

J'aimerais trouver une requete SQL qui supprime les doublons tres vite.

La table n'a pas de clé primaire. La clé primaire est formé avec 3 champs comme vous pouvez le voir sur l'algo d'en haut.

Merci,





Merci
Battosaiii est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 31/05/2011, 12h09   #5
Modérateur
 
Homme Fabien
Ingénieur d'études en décisionnel
Inscription : septembre 2008
Messages : 5 684
Détails du profil
Informations personnelles :
Nom : Homme Fabien
Âge : 34
Localisation : France, Yvelines (Île de France)

Informations professionnelles :
Activité : Ingénieur d'études en décisionnel
Secteur : Arts - Culture

Informations forums :
Inscription : septembre 2008
Messages : 5 684
Points : 10 433
Points : 10 433
Envoyer un message via ICQ à Waldar Envoyer un message via Skype™ à Waldar
Il faudrait fournir plus d'éléments pour vous aider sur la performance, pour commencer :
  • la volumétrie en nombre de lignes et en octets
  • la liste des index de votre table
  • le plan d'exécution de la requête de suppression
__________________
Email : http://scr.im/waldar
Waldar est actuellement connecté   Envoyer un message privé Réponse avec citation 00
Vieux 31/05/2011, 13h51   #6
Membre actif
 
Inscription : mai 2004
Messages : 725
Détails du profil
Informations forums :
Inscription : mai 2004
Messages : 725
Points : 193
Points : 193
Salut,


la volumétrie en nombre de lignes et en octets
->Il y a 180 000 lignes sur cette table.
la liste des index de votre table
-> Il y en a 1 seul index qui comprend la colonne NIP,ID_DEMANDE,TYPE_EXAMEN
le plan d'exécution de la requête de suppression
-> que voulez vous dire par la ?
Battosaiii est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 31/05/2011, 14h09   #7
Modérateur
 
Homme Fabien
Ingénieur d'études en décisionnel
Inscription : septembre 2008
Messages : 5 684
Détails du profil
Informations personnelles :
Nom : Homme Fabien
Âge : 34
Localisation : France, Yvelines (Île de France)

Informations professionnelles :
Activité : Ingénieur d'études en décisionnel
Secteur : Arts - Culture

Informations forums :
Inscription : septembre 2008
Messages : 5 684
Points : 10 433
Points : 10 433
Envoyer un message via ICQ à Waldar Envoyer un message via Skype™ à Waldar
En fait ça va être plutôt simple, vous n'allez pas faire de DELETE du tout !
Supprimer 150.000 lignes sur 180.000, ce n'est pas intéressant, dans ces cas-là il vaut mieux recréer une nouvelle table avec les 30.000 données correctes :
Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
CREATE TABLE radiologie_new
TABLESPACE <votre_tbs>
AS
SELECT *
FROM radiologie r1
 WHERE NOT (ID_EXAMEN LIKE '%*'
   AND EXISTS (SELECT 1
                 FROM radiologie r2
                WHERE r2.DATE_PRESCRIPTION = r1.DATE_PRESCRIPTION
                  AND r2.TYPE_EXAMEN = r1.TYPE_EXAMEN
                  AND r2.ID_DEMANDE = r1.ID_DEMANDE||substr(ID_EXAMEN,1,2)));
 
ALTER TABLE radiologie RENAME TO radiologie_old;
 
ALTER TABLE radiologie_new RENAME TO radiologie;
Puis recréez votre index et repositionnez les droits.
Ce sera beaucoup plus rapide.
__________________
Email : http://scr.im/waldar
Waldar est actuellement connecté   Envoyer un message privé Réponse avec citation 00
Vieux 31/05/2011, 14h33   #8
Membre Expert
 
Avatar de pacmann
 
Homme Pacman Pacman
Business analyst
Inscription : juin 2004
Messages : 1 417
Détails du profil
Informations personnelles :
Nom : Homme Pacman Pacman
Âge : 31
Localisation : France, Paris (Île de France)

Informations professionnelles :
Activité : Business analyst
Secteur : Finance

Informations forums :
Inscription : juin 2004
Messages : 1 417
Points : 2 309
Points : 2 309
Salut !

Le plan d'exécution, c'est ce qui permet de savoir comment Oracle exécute ta requête
... et donc ce qui peut permettre de comprendre pourquoi ça rame
... et donc éventuellement de trouver une solution.

Tu exécutes dans SQL*Plus (par exemple) :
Code :
EXPLAIN PLAN FOR TaRequete
Tu lances ensuite :
Code :
SELECT * FROM TABLE(dbms_xplan.display)
Il y a de fortes chances que ton index ne soit pas utiliser... après, s'il te fait un "filter" ou un truc du genre, ça peut expliquer la lenteur de l'exécution.

Peut être poser un index sur (DATE_PRESCRIPTION,TYPE_EXAMEN,ID_DEMANDE)
?
__________________

(c'est ma photo)
Paku, Paku !
Pour les jeunes incultes : non, je ne suis pas un pokémon...

Le pacblog : http://pacmann.over-blog.com/
pacmann est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 31/05/2011, 23h28   #9
Membre Expert
 
Inscription : août 2008
Messages : 1 271
Détails du profil
Informations forums :
Inscription : août 2008
Messages : 1 271
Points : 1 929
Points : 1 929
Evidemment la proposition de Waldar est très bonne vue le pourcentage de lignes concerné, cependant cette soultion a un problème : il faut connaître le script des droits à réattribuer.

Alors il est peut être possible de retrouver les droits en question via un export de table avec rows=n puis réimport dans un autre schema en précisant le paramêtre log.
Mais pour savoir si ce mode de récupération des grants est total et pérenne il faudrait l'avis d'un dba.
Il y a peut être d'autres moyens mais pareil un dba sera le bien venu pour préciser.

Compte tenu de la volumétrie loin d'être excessive il me semble envisageable de quand même supprimer les lignes.
Mais il est important pour de bonne perf avec le DELETE proposé de passer par un index à cause de la requête corrélée liée à EXISTS.
Dans un 1er temps suit les conseils de Pacmann sinon essaie en modifiant l'ordre des colonnes dans l'index.

Ou alors une version peut être plus fullscan friendly pour du 10g+ pourrait être :
Code :
1
2
3
4
5
6
7
merge INTO radiologie r1
USING (SELECT DATE_PRESCRIPTION, TYPE_EXAMEN, ID_DEMANDE||substr(ID_EXAMEN,1,2) AS id_dem
         FROM radiologie
      ) r2
   ON (r1.DATE_PRESCRIPTION = r2.DATE_PRESCRIPTION AND r1.TYPE_EXAMEN = r2.TYPE_EXAMEN AND r1.ID_DEMANDE = r2.id_dem)
 when matched then DELETE
WHERE r1.ID_EXAMEN LIKE '%*'
Sinon quel est le type de donnée de ID_DEMANDE ? varchar2 ou number ?
skuatamad est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 14/06/2011, 10h45   #10
Membre actif
 
Inscription : mai 2004
Messages : 725
Détails du profil
Informations forums :
Inscription : mai 2004
Messages : 725
Points : 193
Points : 193
Merci pour vos réponses.

Voici la solution que j'ai adopté. J'ai trouvé une clé primaire temporaire rowid.
J'ai supprimé les éléments à partir de rowid.

Code :
1
2
3
4
5
6
7
8
9
10
11
12
 
DELETE FROM radiologie WHERE radiologie.rowid
IN
(
SELECT radio2.rowid
 FROM radiologie radio1,radiologie radio2, fus@db_gip
WHERE radio1.id_demande = radio2.id_demande
AND radio1.type_examen = radio2.type_examen
AND radio1.nip <> radio2.nip
AND radio1.nip = nipact
AND radio2.nip = nipfus
)
Battosaiii est déconnecté   Envoyer un message privé Réponse avec citation 00
Réponse Proposer ce sujet en actualité Cette discussion est résolue.
Outils de la discussion



Fuseau horaire GMT +2. Il est actuellement 20h11.


 
 
 
 
Partenaires

Hébergement Web