J'ai une solution, mais j'ai besoin de l'affiner.
Que faire dans ces cas là :
Cas1
Cas2Tab1 : {4, 5, 8, 9} Tab2 : {1, 2, 3, 7}
Cas3Tab1 : {4, 5, 7, 8} Tab2 : {1, 2, 3, 6}
Tab1 : {4, 5, 8, 9} Tab2 : {1, 2, 3, 6}
J'ai une solution, mais j'ai besoin de l'affiner.
Que faire dans ces cas là :
Cas1
Cas2Tab1 : {4, 5, 8, 9} Tab2 : {1, 2, 3, 7}
Cas3Tab1 : {4, 5, 7, 8} Tab2 : {1, 2, 3, 6}
Tab1 : {4, 5, 8, 9} Tab2 : {1, 2, 3, 6}
Bonjour Waldar,
d'abord merci pour tes réponses, ensuite pour tes cas:
cas1 : normalement dans mon cas on aura jamais ce cas, parce que ma table tab2 contient toujours des lignes triée séquentiellement, donc dans tab2 j'aurais 1,2,3 (le 7 n'a pas sa place dans tab2)
En revanche dans tab1, il est possible d'avoir des séquences avec des trous comme dans ton exemple.
Idem pour les deux autres cas.
je m'inspire de tes cas pour te présenter les cas ci-dessous:
Cas1
Tab1 : {4, 5, 8, 9}
Tab2 : {1, 2, 3}
=> suppression des 8 et 9
Cas2
Tab1 : {4, 5, 7, 8}
Tab2 : {1, 2, 3}
suppression des 7 et 8
Cas3
Tab1 : {4, 5, 8, 9}
Tab2 : {1, 2, 3}
=>suppression de 8 et 9
j'espère que cette fois j'étais claire dans mes explications.
Un truc infâme :
L'idée est de :
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 WITH tab1 AS ( SELECT 1 champ1, 1 champ2, 4 seq FROM DUAL UNION ALL SELECT 1 champ1, 1 champ2, 5 seq FROM DUAL UNION ALL SELECT 1 champ1, 1 champ2, 6 seq FROM DUAL UNION ALL SELECT 1 champ1, 1 champ2, 8 seq FROM DUAL UNION ALL SELECT 2 champ1, 1 champ2, 6 seq FROM DUAL UNION ALL SELECT 2 champ1, 1 champ2, 7 seq FROM DUAL UNION ALL SELECT 2 champ1, 1 champ2, 8 seq FROM DUAL ) , tab2 AS ( SELECT 1 champ1, 1 champ2, 1 seq FROM DUAL UNION ALL SELECT 1 champ1, 1 champ2, 2 seq FROM DUAL UNION ALL SELECT 1 champ1, 1 champ2, 3 seq FROM DUAL UNION ALL SELECT 2 champ1, 1 champ2, 1 seq FROM DUAL UNION ALL SELECT 2 champ1, 1 champ2, 2 seq FROM DUAL UNION ALL SELECT 2 champ1, 1 champ2, 3 seq FROM DUAL ) SELECT champ1, champ2, seq FROM tab1 WHERE (champ1, champ2, seq) IN ( SELECT champ1, champ2, case when seq >= min(trou * seq) over (partition by champ1, champ2 order by seq) then seq end FROM ( SELECT champ1, champ2, seq, case when coalesce(seq - lag(seq,1) over(partition by champ1, champ2 order by seq), 1) <> 1 THEN 1 END trou FROM ( SELECT champ1, champ2, seq FROM tab1 UNION SELECT champ1, champ2, seq FROM tab2 ) ) )
- faire l'union des deux tables
- chercher les trous par champ1, champ2 en utilisant lag
- de chercher quel est le premier avec min (sachant qu'on a mis à null là où il n'y a pas de trou)
- virer tout ce qui est plus grand qui est au dessus de ce trou au sens large...
(Mais avec un peu de chance Waldar aura quelque chose de plus joli )
Si
- il n'y a rien a supprimer dans tab2
- min(tab1) vaut toujours max(tab2)+1 ,
il suffit de jouer ma requete sur tab1 (en place du mot TABLE )
doit on s'interesser au cas :
tab2 : 1 ,2 ,3
tab1 : 7 ,8 ,9
?
ou il faudrait donc vider totalement tab1 ?
EDIT : j'ai relu les messages et ce cas doit vider tab1 donc :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9 DELETE tab1 WHERE seq > (SELECT min (seq) FROM tab1 T1 WHERE NOT EXISTS (SELECT 1 FROM tab1 T2 WHERE T2.seq = T1.seq + 1 ) ) OR (select min (seq ) from tab1) > (select max(seq)+1 from tab2)
J'ai appliqué la méthode de Tabibitosan.
Je suis parti comme Pacmann, j'ai recomposé la liste complète des id et ai simplement cherché le premier trou pour sélectionner tout ce qu'il y a derrière.
Je suppose que la séquence dans Tab2 commence toujours à 1 :
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 WITH tab1 AS ( SELECT 4 as seq FROM dual UNION ALL SELECT 5 FROM dual UNION ALL SELECT 8 FROM dual ) , tab2 as ( SELECT 1 as seq FROM dual UNION ALL SELECT 2 FROM dual UNION ALL SELECT 3 FROM dual ) , tabf as ( select seq from tab1 union select seq from tab2 ) , tabg as ( SELECT seq, seq - row_number() over(order by seq asc) as grp FROM tabf ) SELECT * FROM tab1 WHERE seq in (select seq from tabg where grp > 0); SEQ --- 8
@jean_cri
Tu n'as pas géré le cas 3 par exemple
Cas3
Tab1 : {4, 5, 8, 9}
Tab2 : {1, 2, 3}
=>suppression de 8 et 9
Effectivement Waldar, c'est plus joli en cherchant directement le signe de la différence de rang, bien joué !
@jean_cri : attention aussi au fait qu'il faut opérer ça pour chaque groupe défini par (champ1, champ2) : ta comparaison min - max doit être corrélée à la requête principale.
(Pareil pour Waldar... cela dit de son côté il y a juste quelques GROUP BY / PARTITION BY à ajouter)
@McM : ben si , ca marche
@pacmann : j'ai compris qu'il fallait tout supprimer des la premiere rupture de continuité, c'est pas ca ?
Tout à fait Jean-Cri, mais la rupture, il faut la chercher pour chaque groupe !
(Regarde le post de hammag avec les grosses requêtes, il s'embête vachement à corréler sur <champ1, champ2> un peu partout...)
@pacmann : oui en effet, je me suis basé sur les résumés de ses demandes ou il ne parle jamais des autres champs, et je ne serais pas surpris qu'on lui ai un peu forcé la main pour les utiliser
Le plus simple c'est de le lui demander clairement.
@hammag :
Doit on considerer les sequences pour chaque groupe de champs ? ou peut importe le contenu des autres champs et on ne s'interesse qu'a la valeur de seq ?
Je n'avais même pas percuté qu'il y avait d'autres colonnes.
Avec le même jeu de données :
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
38
39
40
41
42 WITH tab1 AS ( SELECT 1 as c1, 1 as c2, 4 as seq FROM DUAL UNION ALL SELECT 1 , 1 , 5 FROM DUAL UNION ALL SELECT 1 , 1 , 6 FROM DUAL UNION ALL SELECT 1 , 1 , 8 FROM DUAL UNION ALL SELECT 2 , 1 , 6 FROM DUAL UNION ALL SELECT 2 , 1 , 7 FROM DUAL UNION ALL SELECT 2 , 1 , 8 FROM DUAL ) , tab2 AS ( SELECT 1 as c1, 1 as c2, 1 as seq FROM DUAL UNION ALL SELECT 1 , 1 , 2 FROM DUAL UNION ALL SELECT 1 , 1 , 3 FROM DUAL UNION ALL SELECT 2 , 1 , 1 FROM DUAL UNION ALL SELECT 2 , 1 , 2 FROM DUAL UNION ALL SELECT 2 , 1 , 3 FROM DUAL ) , tabf as ( select c1, c2, seq from tab1 union select c1, c2, seq from tab2 ) , tabg as ( SELECT c1, c2, seq, seq - row_number() over(partition by c1, c2 order by seq asc) as grp FROM tabf a ) SELECT * FROM tab1 WHERE (c1, c2, seq) IN (SELECT c1, c2, seq FROM tabg WHERE grp > 0); C1 C2 SEQ -- -- --- 1 1 8 2 1 6 2 1 7 2 1 8
Merci pour tout le monde, mais j'ai enfin trouvé une solution en utilisant une table temporaire et plusieurs requêtes consécutives.
J'ai crée une nouvelle table Temp qui a les mêmes clés de TAB1 et deux autres champs Flag1 et Flag2.
Je copie les lignes de la table TAB1 dans Temp en calculant la valeur des deux champs Flag1 et Flag 2:
1ère requête:
Valeurs de Flag 1 et Flag2
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 INSERT INTO Temp SELECT champ1 ,champ2 ,seq ,CASE WHEN NOT EXISTS (SELECT seq FROM TAB1 WHERE champ1 = A.champ1 AND champ2 = A.champ2 AND seq =A.seq -1 ) THEN 'N' ELSE 'Y' END ,CASE WHEN NOT EXISTS (SELECT seq FROM TAB2 WHERE champ1 = A.champ1 AND champ2 = A.champ2 AND seq =A.seq -1) THEN 'N' ELSE 'Y' END FROM TAB1 A
Pour la ligne i, si la ligne i-1 existe dans TAB1 alors Flag1=Y sinon =N
Pour la ligne i, si la ligne i-1 existe dans TAB2 alors Flag1=Y sinon =N
une 2ème requête: tous les lignes qui ont la séquence 1 seront copiées dans TAB2 (ligne i-1=0 n'a aucun sens)
3ème requête:
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4 UPDATE Temp SET flag1='Y' WHERE Seq=1
la requête 1 met Flag1=flag2=N pour chaque ligne i si cette ligne n'a pas la ligne i-1 ni dans TAB2, ni dans TAB1, et cette ligne sera supprimée.
Donc tous les lignes > i doivent être aussi supprimées. Pour cela il faut mettre les deux champs Flag1=Flag2=N.
enfin, une dernière requête pour supprimer tous les lignes dans TAB1 qui corresponds aux ligne dans Temp avec les deux champs Flag1=Flag2=N.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10 UPDATE Temp a SET flag1='N',flag2='N' WHERE seq >( SELECT MIN(seq) FROM temp WHERE flag1='N' AND flag2='N' AND champ1 = A.champ1 AND champ2 = A.champ2)
voilà, cette solution répond à mes besoin.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13 DELETE FROM TAB1 A WHERE (champ1,champ2,seq) IN ( SELECT champ1 champ2 seq FROM temp WHERE champ1 = A.champ1 AND champ2 = A.champ2 AND seq =A.seq AND flag1='N' AND flag2='N')
chao
non waldar, tu n'a pas répondu dans le vide, ta requête répond parfaitement à mes besoins et je te remercie beaucoup
sauf que moi, j'avais appliqué ma solution avant la réception de ton dernier post.
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