2020-02-28
Il est parfois nécessaire de retirer les accents dans des champs d’une requête PowerQuery / M ou dans une table SQL. Par exemple pour faire une jointure sans avoir à passer par un Fuzzy Lookup.
J’avais imaginé il y a quelques années des solutions compliquées pour faire cela en SQL et en PowerQuery. Mais même si j’aime beaucoup les solutions compliquées, c’est plus simple de faire des choses simples (à cause de la simplicité) …
Donc voici comment simplement retirer les accents d’un texte.
La solution consiste à convertir le code en binaire pour ensuite le repasser en code avec un encodage ASCII.
Pour cela on crée une nouvelle colonne : Text.FromBinary(Text.ToBinary ([#"Texte-avec-accent"], 1251), TextEncoding.Ascii))
let
Source = Table.FromRows(Json.Document(Binary.Decompress(Binary.FromText("NYy5TsNAFAB/5ck1QhENdXr+wLhYzCJW2ogo9kqUEIi470NchcMhbO4joAQIFKP9LwwITTPNTBgGzDBLkznmaZHR5pQzzrlgmx122SvZ54AnnunwwitdFllimRVyCq645oEFLtlklTXW2eCGW+6455AjjjmhxxvvfLDFo89823f5ou/7/jOIBsJgRIl1NUPe0EIRW2VKsUriBnlNi3LTkpY6YXUiZGJHXaUyNKzcmBYTG9GpWLLB31XV/VRF3SWxs38TinFjS5+iJzpJ//NJOnWTKhtE0Tc=", BinaryEncoding.Base64), Compression.Deflate)), let _t = ((type nullable text) meta [Serialized.Text = true]) in type table [#"Texte-avec-accent" = _t]),
#"Personnalisée ajoutée" = Table.AddColumn(Source, "Texte-sans-accent", each Text.FromBinary(Text.ToBinary ([#"Texte-avec-accent"], 1251 ), TextEncoding.Ascii))
in
#"Personnalisée ajoutée"
Merci Denis !
Une autre méthode est d’établir la liste des caractères de substitution et de les remplacer dans le texte initial.
Liste de réference : Liste_Correspondance
let
Source = Table.FromRows(Json.Document(Binary.Decompress(Binary.FromText("RdA5CgJRFETRvbz476j5gYiBiQbSgb0aRxzaoW0HnA3k78vSB97scKGSyjJ7DyxYw2IQh3AEx3ACp7AWu849PMAjPMEznIst5wIuYQkrZjOx6VyJbecabuAWXsTceYU3eIc7sfNj+r7T8/oS+87Hn+kpFhbjBw==", BinaryEncoding.Base64), Compression.Deflate)), let _t = ((type nullable text) meta [Serialized.Text = true]) in type table [ori = _t, des = _t]),
TableToList = Table.ToColumns(Table.Transpose(Source))
in
TableToList
On crée une nouvelle colonne : Table.AddColumn(Source, "Personnalisé", each Text.Combine(List.ReplaceMatchingItems(Text.ToList(Text.Lower([#"Texte-avec-accent"])), Liste_Correspondance)))
let
Source = Table.FromRows(Json.Document(Binary.Decompress(Binary.FromText("NYy5TsNAFAB/5ck1QhENdXr+wLhYzCJW2ogo9kqUEIi470NchcMhbO4joAQIFKP9LwwITTPNTBgGzDBLkznmaZHR5pQzzrlgmx122SvZ54AnnunwwitdFllimRVyCq645oEFLtlklTXW2eCGW+6455AjjjmhxxvvfLDFo89823f5ou/7/jOIBsJgRIl1NUPe0EIRW2VKsUriBnlNi3LTkpY6YXUiZGJHXaUyNKzcmBYTG9GpWLLB31XV/VRF3SWxs38TinFjS5+iJzpJ//NJOnWTKhtE0Tc=", BinaryEncoding.Base64), Compression.Deflate)), let _t = ((type nullable text) meta [Serialized.Text = true]) in type table [#"Texte-avec-accent" = _t]),
#"Added Custom" = Table.AddColumn(Source, "Personnalisé", each Text.Combine(List.ReplaceMatchingItems(Text.ToList(Text.Lower([#"Texte-avec-accent"])), Liste_Correspondance)))
in
#"Added Custom"
Il existe en T-SQL la fonction TRANSLATE qui permet de remplacer les caractère d’une liste, par leur equivalents dans une autre liste.
Par exemple select TRANSLATE('où fuît-il les éphémères ?', 'àéèùî', 'aeeui')
renvoit ou fuit-il les ephemeres ?
On peut donc utiliser la fonction avec la liste de tous les caractères accentués.
DECLARE @avecAccent VARCHAR(55) = 'àáâãäåòóôõöøèéêëðçìíîïùúûüñšÿýž'
DECLARE @sansAccent VARCHAR(55) = 'aaaaaoooooooeeeedciiiiuuuunsyyz'
SELECT [ProduitDesc]
,TRANSLATE([ProduitDesc], @avecAccent, @sansAccent) as [ProduitDescSansAccent]
,[GammeDesc]
,[TypeProduitDesc]
FROM [dbo].[DimProduit]
WHERE TRANSLATE(ProduitDesc, @avecAccent, @sansAccent) <> [ProduitDesc]
Attention : La fonction suit la collation de la base de données. Si la base est configurée comme insensible à la casse ; les caractère seront remplacés par le premier équivalent trouvé majuscules et minuscules confondues. Par exemple select TRANSLATE('où fuît-il les ÉPHÉMÈRES ?', 'àéèùÎ', 'aeeuI')
renvoit ou fuIt-il les ePHeMeRES ?