Dédupliquer et normaliser

Le domaine comme clé, les filiales et les données sales.

Grille de boîtes postales en métal usées

Une liste brute d’entreprises se trompe de deux façons prévisibles : la même société apparaît sous trois noms, et des lignes qui se ressemblent désignent en réalité des sociétés différentes. Corrigez les deux avant de dépenser quoi que ce soit en enrichissement, car tous les chiffres suivants du TAM comptent ces lignes.

Tout au long de ce chapitre, prenons un éditeur de logiciel de paie qui vend aux PME françaises. L’étape d’extraction lui a laissé 18 000 lignes issues du répertoire SIRENE, d’un export LinkedIn et d’un annuaire professionnel. Tous les volumes qui suivent sont fictifs.

Donnez une clé unique à chaque compte avant de comparer quoi que ce soit

Je prends le domaine racine comme clé de compte, parce que c’est l’identifiant que la plupart des sources partagent. Pour les sociétés françaises, j’ajoute le SIREN comme seconde clé, les lignes du répertoire n’ayant souvent pas de site web.

Clé Utile pour Se casse quand
Domaine racine Rapprocher n’importe quelle source, dans n’importe quel pays La société n’a pas de site, ou son « site » est une page sociale
SIREN (9 chiffres) Une unité légale française La ligne vient d’une source qui ne le porte pas
SIRET (14 chiffres) Un établissement Vous l’utilisez comme clé de compte et chaque site devient un client potentiel
URL de page LinkedIn Recouper, puis trouver les personnes La société a plusieurs pages, ou aucune
Nom et ville Dernier recours Deux sociétés portent le même nom, ou l’une utilise un sigle

La confiance suit cet ordre : domaine, puis SIREN, puis LinkedIn. Un nom seul ne fusionne jamais deux lignes automatiquement, puisque deux entreprises sans lien, dans deux départements, peuvent porter le même.

Normalisez les champs sur lesquels vous rapprochez

Ajoutez des colonnes normalisées à côté des colonnes brutes et n’écrasez jamais l’original. Vous en aurez besoin le jour où une fusion se révélera fausse.

Champ Brut Règle Normalisé
domain_root https://www.Acme-Paie.fr/contact?x=1 Minuscules, sans protocole, www, chemin ni paramètres acme-paie.fr
name_norm ACME PAIE S.A.S. Minuscules, sans ponctuation, accents ni forme juridique acme paie
siren 123 456 782 Chiffres seuls, stockés en texte, 9 caractères 123456782
naf_code 62.01Z Majuscules, sans point 6201Z
country France, Fr. Code ISO à deux lettres FR
headcount_band 35 salariés, 11-50 Ramener chaque source à vos propres tranches 10-49 ou 11-50, conservé par source

Dans Google Sheets, avec le site brut en colonne A et le nom brut en colonne B :

=REGEXREPLACE(REGEXREPLACE(LOWER(TRIM(A2)), "^(https?://)?(www\.)?", ""), "[/?#].*$", "")

=TRIM(REGEXREPLACE(REGEXREPLACE(LOWER(B2), "[.,]", ""), "\b(sas|sasu|sarl|eurl|sa|sci|snc)\b", ""))

La première formule conserve les sous-domaines : paie.acme.com et acme.com restent distincts. Filtrez les lignes qui contiennent plus d’un point et corrigez-les à la main, ou passez par une bibliothèque de suffixes publics si vous travaillez en code. Pour les accents, PostgreSQL dispose de l’extension unaccent ; dans un tableur, une chaîne de SUBSTITUTE couvre les cas français.

Rangées de boîtes postales numérotées

Décidez de ce qu’est un compte quand les filiales s’en mêlent

La bonne unité, c’est celle qui signe votre contrat. Écrivez la règle, car votre liste contiendra chacun de ces cas.

Situation Traitement pour un logiciel de paie
Un SIREN, plusieurs SIRET (magasins, usines) Un compte, les établissements dans une table fille
Un domaine, plusieurs SIREN Un compte marqué group_check, jusqu’à savoir qui achète
Plusieurs marques et domaines, un seul propriétaire Comptes séparés, reliés par parent_account_id
Réseau de franchise Un compte par unité légale franchisée, avec une colonne network
Holding sans salarié À garder comme parent seulement, jamais comme PME à démarcher
Filiale française d’un groupe étranger Garder l’entité française, noter le parent

Les données publiques SIRENE décrivent les unités légales et leurs établissements. Elles ne disent pas qui détient qui : les liens de groupe viennent du site de la société, de LinkedIn ou d’une source spécialisée en structures capitalistiques. Ne courez pas après l’actionnariat de 15 000 lignes. Marquez les cas évidents maintenant et traitez le reste quand le scoring vous aura indiqué quels comptes méritent ce travail.

Retirez les lignes qui n’ont rien à faire dans le TAM

Motif Comment le repérer Action
Société cessée etatAdministratifUniteLegale = C dans le fichier SIRENE Retirer
Domaine qui n’appartient pas à la société Liste de blocage : réseaux sociaux, annuaires, créateurs de sites Vider le domaine, garder la ligne
Tranche d’effectif inconnue Code NN du répertoire, qui couvre les unités non employeuses et l’absence d’information Traiter comme inconnu, jamais comme zéro
Valeurs de remplissage N/A, -, en cours de création Vider le champ
Hors ICP sur un critère ferme Secteur ou pays que vous ne servez pas Déplacer dans un onglet excluded, avec la raison

Conservez les lignes exclues quelque part. Elles vous évitent de réimporter les mêmes déchets au prochain rafraîchissement.

Murs de boîtes postales en laiton et vert

Fusionnez avec des règles écrites et gardez la trace

Confiance Règle Action
Haute Même domain_root, ou même siren Fusion automatique
Moyenne Même name_norm et même code postal, domaine différent ou absent File de revue humaine
Faible Même name_norm seulement Laisser séparé

Quand des lignes fusionnent, choisissez le gagnant champ par champ. Le répertoire l’emporte pour la dénomination, le SIREN, le code NAF et l’adresse. Le site de la société ou sa page LinkedIn l’emporte pour le site web. L’effectif reste sur deux colonnes, une par source, car le chapitre suivant a besoin des deux. En SQL, avec source_rank comme entier attribué à chaque source :

WITH ranked AS (
  SELECT *,
    ROW_NUMBER() OVER (
      PARTITION BY domain_root
      ORDER BY (siren IS NOT NULL) DESC, source_rank ASC, collected_at DESC
    ) AS rn
  FROM accounts_raw
  WHERE domain_root IS NOT NULL
)
SELECT * FROM ranked WHERE rn = 1;

Journalisez chaque fusion avec merge_id, kept_account_id, removed_account_id, match_rule et merged_at, pour pouvoir en annuler une sans tout reprendre. Dans notre exemple, l’entonnoir ressemble à ceci :

Étape Lignes restantes
Brut, trois sources 18 000
Après retrait des cessées et du hors périmètre 15 400
Après fusions automatiques sur domaine et SIREN 11 900
Après la file de revue 11 700

Si le compte bouge à peine, vos clés sont probablement trop faibles. Vérifiez la part de lignes sans domaine ni SIREN.

Le faire avec Derrick, ou à la main

J’ai cofondé Derrick, lisez donc ceci en connaissance de cause. Find Duplicates tourne depuis l’application web, la barre latérale Google Sheets, l’API ou un assistant IA via MCP. Vous sélectionnez les colonnes à comparer, une colonne duplicate signale les lignes concernées, et cela ne consomme aucun crédit. Pointez-le sur domain_root plutôt que sur le nom brut. Il ne normalise pas vos valeurs, ne choisit pas la ligne qui survit et ne comprend pas une structure de groupe : les règles ci-dessus restent votre travail.

Pour les lignes françaises qui ont un nom sans SIREN, SIRET/SIREN Enrichment accepte un SIRET, un SIREN ou une dénomination, avec un département facultatif pour lever l’ambiguïté. Il coûte 1 crédit par société et renvoie les données légales, ainsi que matched_name et un score de confiance quand vous cherchez par nom. Envoyez les correspondances fragiles en file de revue : un mauvais SIREN fusionne deux sociétés sans vous prévenir.

La méthode fonctionne sans aucun outil. Une colonne d’aide avec =COUNTIF($C$2:$C,C2)>1 fait le signalement, le SQL ci-dessus choisit les survivants, et le fichier SIRENE sur data.gouv.fr vous donne les identifiants gratuitement si vous acceptez d’écrire le rapprochement par nom vous-même.

Votre prochaine étape : ajoutez les colonnes normalisées à un échantillon de 200 lignes, lisez à la main les correspondances de confiance moyenne et ajustez les règles avant de traiter toute la liste. Le résultat est une table accounts où chaque société a un account_id unique, prête pour l’enrichissement.