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

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.
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.
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.