[RESOLU][SQL] Trouver les groupes doublons avec un nombre indéfini de membres

Messieurs dames bien le bonjour

Petite question aux spécialistes SQL qui ont déjà fini de désaoûler d’hier:

1. Ze context:
Dans le cadre d’un script perl que je développe pour automatiser le nettoyage et la réécriture de la conf de firewalls, via du parsing et des requêtes SQL j’ai mis dans une DB MySQL tous les objets de la conf du firewall.
Dans ces objets, il y a entre autre des groupes. Et qui dit groupes, dit membres d’un groupe. J’ai ces tables-ci:

oldgroup: name (varchar 30), comment (varchar 50), scope (tinyint), translated (bool)
membersinoldgroup: id (int 10), groupname (varchar 30), object (varchar 30), objecttype (varchar 10)
et des tables avec pour les différents types d’objets: hosts, réseaux, ranges, etc.

2. Ze problem
Comme j’aime le travail bien fait, et que ceux qui sur les mois précédents ont fait un travail de sagouin à cause de règles d’exploit merdiques, je voudrais éviter qu’on ait 25 groupes avec exactement les mêmes membres dedans. Donc en gros, ça veut dire trouver tous les membersinoldgroup.groupname qui ont les mêmes membersinoldgroup.object associés. Sauf que pour que ce soit drôle, le nombre de membres est variable, de… 1 (ouais, vive les groupes à un seul membre, c’est super utile) à une cinquantaine.

Genre si j’ai dans membersinoldgroup (je mets pas le contenu des colonnes id et objecttype, on s’en fout):
group1, membreX
group1, membreY
group1, membreZ
group2, membreX
group2, membreZ
group2, membreY

Comment que je retrouve que group1 et group2 n’ont pour seule différence que leur nom et que ce serait bien qu’ils ne fassent plus qu’un?

3. Ze solucheune
Là je compte sur vous. Sinon ce thread n’aurait pas d’intérêt.

Essaie ça :

[sql]select
groupe.name,
(select group_concat(membregroupe.object) from membregroupe where membregroupe.group = groupe.name order by membregroupe.object)
from
groupe[/sql]
la fonction group_concat permet de fusionner les lignes d’un select dans une seule chaine.

Pour chaque groupe, tu obtiendras la liste des membres. tu n’as donc qu’à trier ton résultat pour obtenir les groupes qui ont exactement les mêmes membres.

Par contre cette requête ne t’aide pas pour trouver les groupes “à peu près” similaires.

PS : je n’ai pas testé ce code n’ayant pas mysql sous la main.

Sur developpez.com: Les doublons : détection et éradication…

J’ai suggéré ca:

http://pastebin.com/wTR69EV6

SELECT * FROM ( SELECT GROUP_CONCAT( DISTINCT t.groupname ), s.cnt AS object_count, COUNT(*) AS group_count FROM test t, (SELECT j.groupname, COUNT(*) AS cnt, GROUP_CONCAT( j.object ORDER BY col_name) as members FROM test j GROUP BY j.groupname) AS s WHERE t.groupname = s.groupname GROUP BY s.members ) AS x WHERE group_count / object_count >= 2

Je pense qu’on peut faire plus simple, mais ca marche

La solution de Cil-Taff qui est bonne (merci Styx31 pour la piste du group_concat)

SELECT * FROM ( SELECT GROUP_CONCAT( DISTINCT t.groupname ), s.cnt AS object_count, COUNT(*) AS group_count FROM test t, (SELECT j.groupname, COUNT(*) AS cnt, GROUP_CONCAT( j.object ORDER BY object) as members FROM test j GROUP BY j.groupname) AS s WHERE t.groupname = s.groupname GROUP BY s.members ) AS x WHERE group_count / object_count >= 2

[quote=“phili_b, post:3, topic: 51439”]
Sur developpez.com: Les doublons : détection et éradication…
[/quote]

Excellent article, ça me servira la prochaine fois