Inférence basique avec gestion de collation

Afin de compléter cet article sur la recherche de motifs (rapprochement de chaines de caractères), voici une version qui gère la casse et les accents.


CREATE FUNCTION dbo.F_INFERENCE_BASIQUE (@SOURCE VARCHAR(8000),
                                         @CIBLE  VARCHAR(8000),
                                         @CS BIT,  
                                         @AS BIT )  
RETURNS FLOAT
AS
/******************************************************************************
* Fonction de calcul de rapprochement entre deux chaines de caractères        *
*******************************************************************************
* Fred. Brouard - http://sqlpro.developpez.com - www.sqlspot.com - 2009-10-26 *
*******************************************************************************
* donne un indice de rapprochement etre deux chaines pour comparaison avec    *
* différentes occurrences                                                     *
* @SOURCE est la chaine source                                                *
* @CIBLE est la chaine cible                                                  *
* Si @CS vaut 1 alors la comparaison est sensible à la casse                  *
* Si @AS vaut 1 alors la comparaison est sensible aux caractères diacritiques *
* (accents, cédille....)                                                      *
******************************************************************************/
BEGIN
 
IF @SOURCE IS NULL OR @CIBLE IS NULL RETURN NULL;
IF @SOURCE = '' OR @CIBLE = '' RETURN 0;
SET @CS = COALESCE(@CS, 0);
SET @AS = COALESCE(@AS, 0);
 
DECLARE @COUNT1 INT, @COUNT2 INT
DECLARE @I INT, @J INT, @L INT
DECLARE @C CHAR(1), @X INT
 
SET @COUNT1 = 0
SET @COUNT2 = 0
 
SET @I = 1
SET @J = 1
SET @L = LEN(@SOURCE)
 
-- première passe source vers cible
WHILE @I <= @L
BEGIN
   SET @C = SUBSTRING(@SOURCE, @I, 1)
   SET @X = CASE  
            WHEN @CS = 1 AND @AS = 1  
               THEN CHARINDEX(@C COLLATE French_CS_AS, @CIBLE COLLATE French_CS_AS, @J)
            WHEN @CS = 1 AND @AS = 0  
               THEN CHARINDEX(@C COLLATE French_CS_AI, @CIBLE COLLATE French_CS_AI, @J)
            WHEN @CS = 0 AND @AS = 1  
               THEN CHARINDEX(@C COLLATE French_CI_AS, @CIBLE COLLATE French_CI_AS, @J)
            WHEN @CS = 0 AND @AS = 0  
               THEN CHARINDEX(@C COLLATE French_CI_AI, @CIBLE COLLATE French_CI_AI, @J)
            END;
   IF @X > 0
   BEGIN
      SET @COUNT1 = @COUNT1 + 1
      SET @J = @X + 1
      SET @I = @I + 1
      CONTINUE
   END
   SET @I = @I + 1
END
 
IF @COUNT1 = 0 RETURN 0
 
SET @I = 1
SET @J = 1
SET @L = LEN(@CIBLE)
 
-- seconde passe cible vers source
WHILE @I <= @L
BEGIN
   SET @C = SUBSTRING(@CIBLE, @I, 1)
   SET @X = CASE  
            WHEN @CS = 1 AND @AS = 1  
               THEN CHARINDEX(@C COLLATE French_CS_AS, @SOURCE COLLATE French_CS_AS, @J)
            WHEN @CS = 1 AND @AS = 0  
               THEN CHARINDEX(@C COLLATE French_CS_AI, @SOURCE COLLATE French_CS_AI, @J)
            WHEN @CS = 0 AND @AS = 1  
               THEN CHARINDEX(@C COLLATE French_CI_AS, @SOURCE COLLATE French_CI_AS, @J)
            WHEN @CS = 0 AND @AS = 0  
               THEN CHARINDEX(@C COLLATE French_CI_AI, @SOURCE COLLATE French_CI_AI, @J)
            END;
   
   IF @X > 0
   BEGIN
      SET @COUNT2 = @COUNT2 + 1
      SET @J = @X + 1
      SET @I = @I + 1
      CONTINUE
   END
   SET @I = @I + 1
END
 
RETURN CAST(CASE WHEN @COUNT1 < @COUNT2 THEN @COUNT2 ELSE @COUNT1 END AS FLOAT)  
    /  CAST(CASE WHEN LEN(@SOURCE) < LEN(@CIBLE) THEN LEN(@CIBLE) ELSE LEN(@SOURCE) END AS FLOAT)
 
END
 
GO


Frédéric BROUARD, Spécialiste modélisation, bases de données, optimisation, langage SQL.
Le site sur le langage SQL et les S.G.B.D. relationnels : http://sqlpro.developpez.com/
Expert SQL Server http://www.sqlspot.com : audit, optimisation, tuning, formation
* * * * * Enseignant au CNAM PACA et à l’ISEN à Toulon * * * * *

Laisser un commentaire