Meilleure méthode de SQL Server pour faire correspondre les expressions de mots et la pertinence des commands

Quelle est la meilleure façon de classr une colonne varchar sql par le nombre (nombre) / correspondance de mots dans un paramètre, avec quatre critères uniques distincts. Ce n'est probablement pas une question sortingviale, mais je suis mis au défi d'ordonner les lignes basées sur le «meilleur match» en utilisant mes critères.

colonne: description varchar (100) Paramètre: @MyParameter varchar (100)

Sortie avec cette preference de command:

  • Correspondance exacte (strings entières) – toujours en premier
  • Commence par (décount basé sur la longueur du paramètre de correspondance)
  • Nombre de mots avec des mots contigus se classant plus haut pour le même nombre de mots correspondants
  • Word (s) correspond n'importe où (pas contigu)

Les mots peuvent NE PAS correspondre exactement, car les correspondances partielles d'un mot sont autorisées et probablement, la valeur du bailleur devrait être appliquée aux mots partiels pour le classment mais pas critique (pot correspondrait à: pot, potier, manique, repository, repository par exemple). Commence par avec d'autres correspondances de mots devrait être plus élevé que ceux sans autres correspondances mais ce n'est pas un deal killer / super important.

Je voudrais avoir une méthode pour classr où la colonne "commence par" la valeur dans le paramètre. Dites que j'ai la string suivante:

'This is my value ssortingng as a test template to rank on.' 

Je voudrais avoir, dans le premier cas, un rang de la colonne / rangée où le plus grand nombre de mots existe.

Et la deuxième à classr en fonction de l'occurance (meilleur match) au début comme:

 'This is my ssortingng as a test template to rank on.' - first 'This is my ssortingng as a test template to rank on even though not exact.'-second 'This is my ssortingng as a test template to rank' - third 'This is my ssortingng as a test template to' - next 'This is my ssortingng as a test template' - next etc. 

Deuxièmement: (éventuellement deuxième set / groupe de données après le premier (commence par) – cela est souhaité

Je veux classr (sortinger) les lignes par le nombre de mots dans le @MyParameter qui se produisent dans @MyParameter avec un rang où les mots contigus se classnt plus haut que le même nombre séparé.

Ainsi, pour l'exemple de string ci-dessus, 'is my ssortingng as shown' serait plus haute que 'is not my other ssortingng as' raison de la "meilleure correspondance" de la string contiguë (mots set) avec le même nombre de mots. Les lignes avec une correspondance plus élevée (nombre de mots qui se produisent) se classraient en ordre décroissant en premier.

Si possible, j'aimerais le faire en une seule requête.

Aucune ligne ne doit apparaître deux fois dans le résultat.

Pour des considérations de performance, il ne se produira pas plus de 10 000 lignes dans la table.

Les valeurs dans le tableau sont assez statiques avec peu de changement mais pas totalement.

Je ne peux pas changer la structure pour le moment mais je considérerais cela plus tard (comme un tableau de mots / phrases)

Pour rendre cela un peu plus compliqué, la list des mots se trouve dans deux arrays – mais je pourrais créer une vue pour cela, mais les résultats d'une table (list plus petite) devraient se produire avant une seconde. être dupliqués à partir de ces tables ainsi que dans une table et je veux seulement des valeurs distinctes. Select DISTINCT n'est pas facile car je veux returnner une colonne (sourceTable) qui pourrait très bien rendre les lignes distinctes et dans ce cas sélectionner uniquement dans la première (plus petite) table, mais toutes les autres colonnes DISTINCT sont souhaitées (ne pas considérer que colonne dans l'évaluation "distincte".

Colonnes de Psuedo dans la table:

 procedureCode VARCHAR(50), description VARCHAR(100), -- this is the sort/evaluation column category VARCHAR(50), relvu VARCHAR(50), charge VARCHAR(15), active bit sourceTable VARCHAR(50) - just shows which table it comes from of the two 

Aucun index unique n'existe comme une colonne d'ID

Correspond à la troisième table à exclure SELECT * FROM (select * from tableone where procedureCode not in (select procedureCode from tablethree)) UNION ALL (select * from tabletwo where procedureCode not in (select procedureCode from tablethree))

EDIT: pour tenter de résoudre ce problème, j'ai créé un paramètre de valeur de table comme ceci:

 0 Gassortingc Intubation & Aspiration/Lavage, Treatmen 1 Gassortingc%Intubation%Aspiration%Lavage%Treatmen 2 Gassortingc%Intubation%Aspiration%Lavage 3 Gassortingc%Intubation%Aspiration 4 Gassortingc%Intubation 5 Gassortingc 6 Intubation%Aspiration%Lavage%Treatmen 7 Intubation%Aspiration%Lavage 8 Intubation%Aspiration 9 Intubation 10 Aspiration%Lavage%Treatmen 11 Aspiration%Lavage 12 Aspiration 13 Lavage%Treatmen 14 Lavage 15 Treatmen 

où la phrase réelle est dans la rangée 0

Voici ma tentative actuelle à ceci:

 CREATE PROCEDURE [GetProcedureByDescription] ( @IncludeMaster BIT, @ProcedureSearchPhrases CPTFavorite READONLY ) AS DECLARE @myIncludeMaster BIT; SET @myIncludeMaster = @IncludeMaster; CREATE TABLE #DistinctMatchingCpts ( procedureCode VARCHAR(50), description VARCHAR(100), category VARCHAR(50), rvu VARCHAR(50), charge VARCHAR(15), active VARCHAR(15), sourceTable VARCHAR(50), sequenceSet VARCHAR(2) ) IF @myIncludeMaster = 0 BEGIN -- Excluding master from search INSERT INTO #DistinctMatchingCpts (sourceTable, procedureCode, description , category ,charge, active, rvu, sequenceSet ) SELECT DISTINCT sourceTable, procedureCode, description, category ,charge, active, rvu, sequenceSet FROM ( SELECT TOP 1 LTRIM(RTRIM(CPT.[CODE])) AS procedureCode, LTRIM(RTRIM(CPT.[LEVEL])) AS description, LTRIM(RTRIM(CPT.[COMBO])) AS category, LTRIM(RTRIM(CPT.[CHARGE])) AS charge, ''True'' AS active, LTRIM(RTRIM([RVU])) AS rvu, ''0CPTMore'' AS sourceTable, ''01'' AS sequenceSet FROM @ProcedureSearchPhrases PP INNER JOIN [CPTMORE] AS CPT ON CPT.[LEVEL] = PP.[LEVEL] WHERE (CPT.[COMBO] IS NULL OR CPT.[COMBO] NOT IN (''Editor'',''MOD'',''CATEGORY'',''Types'',''Bundles'')) AND CPT.[CODE] IS NOT NULL AND CPT.[CODE] NOT IN (''0'', '''') AND CPT.[CODE] NOT IN (SELECT CPTE.[CODE] FROM CPT AS CPTE WHERE CPTE.[CODE] IS NOT NULL) ORDER BY PP.CODE UNION ALL SELECT LTRIM(RTRIM(CPT.[CODE])) AS procedureCode, LTRIM(RTRIM(CPT.[LEVEL])) AS description, LTRIM(RTRIM(CPT.[COMBO])) AS category, LTRIM(RTRIM([CHARGE])) AS charge, ''True'' AS active, LTRIM(RTRIM([RVU])) AS rvu, ''0CPTMore'' AS sourceTable, ''02'' AS sequenceSet FROM @ProcedureSearchPhrases PP INNER JOIN [CPTMORE] AS CPT ON CPT.[LEVEL] LIKE PP.[LEVEL] + ''%'' WHERE (CPT.[COMBO] IS NULL OR CPT.[COMBO] NOT IN (''Editor'',''MOD'',''CATEGORY'',''Types'',''Bundles'')) AND CPT.[CODE] IS NOT NULL AND CPT.[CODE] NOT IN (''0'', '''') AND CPT.[CODE] NOT IN (SELECT CPTE.[CODE] FROM CPT AS CPTE WHERE CPTE.[CODE] IS NOT NULL) UNION ALL SELECT LTRIM(RTRIM(CPT.[CODE])) AS procedureCode, LTRIM(RTRIM(CPT.[LEVEL])) AS description, LTRIM(RTRIM(CPT.[COMBO])) AS category, LTRIM(RTRIM(CPT.[CHARGE])) AS charge, ''True'' AS active, LTRIM(RTRIM([RVU])) AS rvu, ''0CPTMore'' AS sourceTable, ''03'' AS sequenceSet FROM @ProcedureSearchPhrases PP INNER JOIN [CPTMORE] AS CPT ON CPT.[LEVEL] LIKE ''%'' + PP.[LEVEL] + ''%'' WHERE (CPT.[COMBO] IS NULL OR CPT.[COMBO] NOT IN (''Editor'',''MOD'',''CATEGORY'',''Types'',''Bundles'')) AND CPT.[CODE] IS NOT NULL AND CPT.[CODE] NOT IN (''0'', '''') AND CPT.[CODE] NOT IN (SELECT CPTE.[CODE] FROM CPT AS CPTE WHERE CPTE.[CODE] IS NOT NULL) ) AS CPTS ORDER BY procedureCode, sourceTable, [description] END -- Excluded master from search ELSE BEGIN -- Including master in search, but present favorites before master for each code -- Get matching procedures, ordered by code, source (favorites first), and description. -- There probably will be procedures with duplicated code+description, so we will filter -- duplicates shortly. INSERT INTO #DistinctMatchingCpts (sourceTable, procedureCode, description , category ,charge, active, rvu, sequenceSet) SELECT DISTINCT sourceTable, procedureCode, description, category ,charge, active, rvu, sequenceSet FROM ( SELECT TOP 1 LTRIM(RTRIM(CPT.[CODE])) AS procedureCode, LTRIM(RTRIM(CPT.[LEVEL])) AS description, LTRIM(RTRIM(CPT.[COMBO])) AS category, LTRIM(RTRIM(CPT.[CHARGE])) AS charge, ''True'' AS active, LTRIM(RTRIM([RVU])) AS rvu, ''0CPTMore'' AS sourceTable, ''00'' AS sequenceSet FROM @ProcedureSearchPhrases PP INNER JOIN [CPTMORE] AS CPT ON CPT.[LEVEL] = PP.[LEVEL] WHERE (CPT.[COMBO] IS NULL OR CPT.[COMBO] NOT IN (''Editor'',''MOD'',''CATEGORY'',''Types'',''Bundles'')) AND CPT.[CODE] IS NOT NULL AND CPT.[CODE] NOT IN (''0'', '''') AND CPT.[CODE] NOT IN (SELECT CPTE.[CODE] FROM CPT AS CPTE WHERE CPTE.[CODE] IS NOT NULL) ORDER BY PP.CODE UNION ALL SELECT TOP 1 LTRIM(RTRIM(CPT.[CODE])) AS procedureCode, LTRIM(RTRIM(CPT.[LEVEL])) AS description, LTRIM(RTRIM(CPT.[CATEGORY])) AS category, LTRIM(RTRIM(CPT.[CHARGE])) AS charge, COALESCE(CASE [ACTIVE] WHEN 1 THEN ''True'' WHEN 0 THEN ''False'' WHEN '''' THEN ''False'' ELSE ''False'' END,''True'') AS active, LTRIM(RTRIM([RVU])) AS rvu, ''2MasterCPT'' AS sourceTable, ''00'' AS sequenceSet FROM @ProcedureSearchPhrases PP INNER JOIN [MASTERCPT] AS CPT ON CPT.[LEVEL] = PP.[LEVEL] WHERE CPT.[CODE] IS NOT NULL AND CPT.[CODE] NOT IN (''0'', '''') AND CPT.[CODE] NOT IN (SELECT CPTE.[CODE] FROM CPT AS CPTE WHERE CPTE.[CODE] IS NOT NULL) ORDER BY PP.CODE UNION ALL SELECT LTRIM(RTRIM(CPT.[CODE])) AS procedureCode, LTRIM(RTRIM(CPT.[LEVEL])) AS description, LTRIM(RTRIM(CPT.[COMBO])) AS category, LTRIM(RTRIM(CPT.[CHARGE])) AS charge, ''True'' AS active, LTRIM(RTRIM([RVU])) AS rvu, ''0CPTMore'' AS sourceTable, ''01'' AS sequenceSet FROM @ProcedureSearchPhrases PP INNER JOIN [CPTMORE] AS CPT ON CPT.[LEVEL] = PP.[LEVEL] WHERE (CPT.[COMBO] IS NULL OR CPT.[COMBO] NOT IN (''Editor'',''MOD'',''CATEGORY'',''Types'',''Bundles'')) AND CPT.[CODE] IS NOT NULL AND CPT.[CODE] NOT IN (''0'', '''') AND CPT.[CODE] NOT IN (SELECT CPTE.[CODE] FROM CPT AS CPTE WHERE CPTE.[CODE] IS NOT NULL) UNION ALL SELECT LTRIM(RTRIM(CPT.[CODE])) AS procedureCode, LTRIM(RTRIM(CPT.[LEVEL])) AS description, LTRIM(RTRIM(CPT.[CATEGORY])) AS category, LTRIM(RTRIM(CPT.[CHARGE])) AS charge, COALESCE(CASE [ACTIVE] WHEN 1 THEN ''True'' WHEN 0 THEN ''False'' WHEN '''' THEN ''False'' ELSE ''False'' END,''True'') AS active, LTRIM(RTRIM([RVU])) AS rvu, ''2MasterCPT'' AS sourceTable, ''01'' AS sequenceSet FROM @ProcedureSearchPhrases PP INNER JOIN [MASTERCPT] AS CPT ON CPT.[LEVEL] = PP.[LEVEL] WHERE CPT.[CODE] IS NOT NULL AND CPT.[CODE] NOT IN (''0'', '''') AND CPT.[CODE] NOT IN (SELECT CPTE.[CODE] FROM CPT AS CPTE WHERE CPTE.[CODE] IS NOT NULL) UNION ALL SELECT TOP 1 LTRIM(RTRIM(CPT.[CODE])) AS procedureCode, LTRIM(RTRIM(CPT.[LEVEL])) AS description, LTRIM(RTRIM(CPT.[COMBO])) AS category, LTRIM(RTRIM(CPT.[CHARGE])) AS charge, ''True'' AS active, LTRIM(RTRIM([RVU])) AS rvu, ''0CPTMore'' AS sourceTable, ''02'' AS sequenceSet FROM @ProcedureSearchPhrases PP INNER JOIN [CPTMORE] AS CPT ON CPT.[LEVEL] LIKE PP.[LEVEL] + ''%'' WHERE (CPT.[COMBO] IS NULL OR CPT.[COMBO] NOT IN (''Editor'',''MOD'',''CATEGORY'',''Types'',''Bundles'')) AND CPT.[CODE] IS NOT NULL AND CPT.[CODE] NOT IN (''0'', '''') AND CPT.[CODE] NOT IN (SELECT CPTE.[CODE] FROM CPT AS CPTE WHERE CPTE.[CODE] IS NOT NULL) ORDER BY PP.CODE UNION ALL SELECT TOP 1 LTRIM(RTRIM(CPT.[CODE])) AS procedureCode, LTRIM(RTRIM(CPT.[LEVEL])) AS description, LTRIM(RTRIM(CPT.[CATEGORY])) AS category, LTRIM(RTRIM(CPT.[CHARGE])) AS charge, COALESCE(CASE [ACTIVE] WHEN 1 THEN ''True'' WHEN 0 THEN ''False'' WHEN '''' THEN ''False'' ELSE ''False'' END,''True'') AS active, LTRIM(RTRIM([RVU])) AS rvu, ''2MasterCPT'' AS sourceTable, ''02'' AS sequenceSet FROM @ProcedureSearchPhrases PP INNER JOIN [MASTERCPT] AS CPT ON CPT.[LEVEL] LIKE PP.[LEVEL] + ''%'' WHERE CPT.[CODE] IS NOT NULL AND CPT.[CODE] NOT IN (''0'', '''') AND CPT.[CODE] NOT IN (SELECT CPTE.[CODE] FROM CPT AS CPTE WHERE CPTE.[CODE] IS NOT NULL) ORDER BY PP.CODE UNION ALL SELECT LTRIM(RTRIM(CPT.[CODE])) AS procedureCode, LTRIM(RTRIM(CPT.[LEVEL])) AS description, LTRIM(RTRIM(CPT.[COMBO])) AS category, LTRIM(RTRIM(CPT.[CHARGE])) AS charge, ''True'' AS active, LTRIM(RTRIM([RVU])) AS rvu, ''0CPTMore'' AS sourceTable, ''03'' AS sequenceSet FROM @ProcedureSearchPhrases PP INNER JOIN [CPTMORE] AS CPT ON CPT.[LEVEL] LIKE PP.[LEVEL] + ''%'' WHERE (CPT.[COMBO] IS NULL OR CPT.[COMBO] NOT IN (''Editor'',''MOD'',''CATEGORY'',''Types'',''Bundles'')) AND CPT.[CODE] IS NOT NULL AND CPT.[CODE] NOT IN (''0'', '''') AND CPT.[CODE] NOT IN (SELECT CPTE.[CODE] FROM CPT AS CPTE WHERE CPTE.[CODE] IS NOT NULL) UNION ALL SELECT LTRIM(RTRIM(CPT.[CODE])) AS procedureCode, LTRIM(RTRIM(CPT.[LEVEL])) AS description, LTRIM(RTRIM(CPT.[CATEGORY])) AS category, LTRIM(RTRIM(CPT.[CHARGE])) AS charge, COALESCE(CASE [ACTIVE] WHEN 1 THEN ''True'' WHEN 0 THEN ''False'' WHEN '''' THEN ''False'' ELSE ''False'' END,''True'') AS active, LTRIM(RTRIM([RVU])) AS rvu, ''2MasterCPT'' AS sourceTable, ''03'' AS sequenceSet FROM @ProcedureSearchPhrases PP INNER JOIN [MASTERCPT] AS CPT ON CPT.[LEVEL] LIKE PP.[LEVEL] + ''%'' WHERE CPT.[CODE] IS NOT NULL AND CPT.[CODE] NOT IN (''0'', '''') AND CPT.[CODE] NOT IN (SELECT CPTE.[CODE] FROM CPT AS CPTE WHERE CPTE.[CODE] IS NOT NULL) UNION ALL SELECT LTRIM(RTRIM(CPT.[CODE])) AS procedureCode, LTRIM(RTRIM(CPT.[LEVEL])) AS description, LTRIM(RTRIM(CPT.[COMBO])) AS category, LTRIM(RTRIM(CPT.[CHARGE])) AS charge, ''True'' AS active, LTRIM(RTRIM([RVU])) AS rvu, ''0CPTMore'' AS sourceTable, ''04'' AS sequenceSet FROM @ProcedureSearchPhrases PP INNER JOIN [CPTMORE] AS CPT ON CPT.[LEVEL] LIKE ''%'' + PP.[LEVEL] + ''%'' WHERE (CPT.[COMBO] IS NULL OR CPT.[COMBO] NOT IN (''Editor'',''MOD'',''CATEGORY'',''Types'',''Bundles'')) AND CPT.[CODE] IS NOT NULL AND CPT.[CODE] NOT IN (''0'', '''') AND CPT.[CODE] NOT IN (SELECT CPTE.[CODE] FROM CPT AS CPTE WHERE CPTE.[CODE] IS NOT NULL) UNION ALL SELECT LTRIM(RTRIM(CPT.[CODE])) AS procedureCode, LTRIM(RTRIM(CPT.[LEVEL])) AS description, LTRIM(RTRIM(CPT.[CATEGORY])) AS category, LTRIM(RTRIM(CPT.[CHARGE])) AS charge, COALESCE(CASE [ACTIVE] WHEN 1 THEN ''True'' WHEN 0 THEN ''False'' WHEN '''' THEN ''False'' ELSE ''False'' END,''True'') AS active, LTRIM(RTRIM([RVU])) AS rvu, ''2MasterCPT'' AS sourceTable, ''04'' AS sequenceSet FROM @ProcedureSearchPhrases PP INNER JOIN [MASTERCPT] AS CPT ON CPT.[LEVEL] LIKE ''%'' + PP.[LEVEL] + ''%'' WHERE CPT.[CODE] IS NOT NULL AND CPT.[CODE] NOT IN (''0'', '''') AND CPT.[CODE] NOT IN (SELECT CPTE.[CODE] FROM CPT AS CPTE WHERE CPTE.[CODE] IS NOT NULL) ) AS CPTS ORDER BY sequenceSet, sourceTable, [description] END /* Final select - uses artificial ordering from the insertion ORDER BY */ SELECT procedureCode, description, category, rvu, charge, active FROM ( SELECT TOP 500 *-- procedureCode, description, category, rvu, charge, active FROM #DistinctMatchingCpts ORDER BY sequenceSet, sourceTable, description ) AS CPTROWS DROP TABLE #DistinctMatchingCpts 

Cependant, cela ne répond PAS aux critères de la meilleure correspondance sur le nombre de mots (comme dans la valeur de la ligne 1 de l'échantillon) qui doit correspondre au meilleur (le plus grand nombre) de mots trouvés à partir de cette ligne.

J'ai un contrôle complet sur la forme / le format du paramètre de valeur de table si cela fait une différence.

Je returnne ce résultat au programme AC # si cela est utile.

Vous devez être capable de séparer les strings pour résoudre ce problème. Je préfère l'approche de la table numérique pour séparer une string dans TSQL

Pour mon code ci-dessous pour travailler (ainsi que ma fonction split), vous devez faire ce réglage de la table de time:

 SELECT TOP 10000 IDENTITY(int,1,1) AS Number INTO Numbers FROM sys.objects s1 CROSS JOIN sys.objects s2 ALTER TABLE Numbers ADD CONSTRAINT PK_Numbers PRIMARY KEY CLUSTERED (Number) 

Une fois la table Numbers configurée, créez cette fonction de partage:

 CREATE FUNCTION [dbo].[FN_ListToTable] ( @SplitOn char(1) --REQUIRED, the character to split the @List ssortingng on ,@List varchar(8000)--REQUIRED, the list to split apart ) RETURNS TABLE AS RETURN ( ---------------- --SINGLE QUERY-- --this will not return empty rows ---------------- SELECT ListValue FROM (SELECT LTRIM(RTRIM(SUBSTRING(List2, number+1, CHARINDEX(@SplitOn, List2, number+1)-number - 1))) AS ListValue FROM ( SELECT @SplitOn + @List + @SplitOn AS List2 ) AS dt INNER JOIN Numbers n ON n.Number < LEN(dt.List2) WHERE SUBSTRING(List2, number, 1) = @SplitOn ) dt2 WHERE ListValue IS NOT NULL AND ListValue!='' ); GO 

N'hésitez pas à créer votre propre fonction de partage, mais vous avez toujours besoin de la table Numbers pour que ma solution fonctionne.

Vous pouvez maintenant facilement split une string CSV en une table et la joindre:

 select * from dbo.FN_ListToTable(',','1,2,3,,,4,5,6777,,,') 

SORTIE:

 ListValue ----------------------- 1 2 3 4 5 6777 (6 row(s) affected) 

Maintenant, essayez ceci:

 DECLARE @BaseTable table (RowID int primary key, RowValue varchar(100)) set nocount on INSERT @BaseTable VALUES ( 1,'The cows came home empty handed') INSERT @BaseTable VALUES ( 2,'This is my ssortingng as a test template to rank') -- third INSERT @BaseTable VALUES ( 3,'pencil pen paperclip eraser') INSERT @BaseTable VALUES ( 4,'wow') INSERT @BaseTable VALUES ( 5,'no dice here') INSERT @BaseTable VALUES ( 6,'This is my ssortingng as a test template to rank on even though not exact.') -- second INSERT @BaseTable VALUES ( 7,'apple banana pear grape lemon orange kiwi strawberry peach watermellon') INSERT @BaseTable VALUES ( 8,'This is my ssortingng as a test template') -- 5th INSERT @BaseTable VALUES ( 9,'rat cat bat mat sat fat hat pat ') INSERT @BaseTable VALUES (10,'house home pool roll') INSERT @BaseTable VALUES (11,'This is my ssortingng as a test template to') -- 4th INSERT @BaseTable VALUES (12,'talk wisper yell scream sing hum') INSERT @BaseTable VALUES (13,'This is my ssortingng as a test template to rank on.') -- first INSERT @BaseTable VALUES (14,'aaa bbb ccc ddd eee fff ggg hhh') INSERT @BaseTable VALUES (15,'three twice three once twice three') set nocount off DECLARE @SearchValue varchar(100) SET @SearchValue='This is my value ssortingng as a test template to rank on.' ;WITH SplitBaseTable AS --expand each @BaseTable row into one row per word (SELECT b.RowID, b.RowValue, s.ListValue FROM @BaseTable b CROSS APPLY dbo.FN_ListToTable(' ',b.RowValue) AS s ) , WordMatchCount AS --for each @BaseTable row that has has a word in common withe the search ssortingng, get the count of matching words (SELECT s.RowID,COUNT(*) AS CountOfWordMatch FROM dbo.FN_ListToTable(' ',@SearchValue) v INNER JOIN SplitBaseTable s ON v.ListValue=s.ListValue GROUP BY s.RowID HAVING COUNT(*)>0 ) , SearchLen AS --get one row for each possible length of the search ssortingng ( SELECT n.Number,SUBSTRING(@SearchValue,1,n.Number) AS PartialSearchValue FROM Numbers n WHERE n.Number<=LEN(@SearchValue) ) , MatchLen AS --for each @BaseTable row, get the max starting length that matches the search ssortingng ( SELECT b.RowID,MAX(l.Number) MatchStartLen FROM @BaseTable b LEFT OUTER JOIN SearchLen l ON LEFT(b.RowValue,l.Number)=l.PartialSearchValue GROUP BY b.RowID ) SELECT --return the final search results b.RowValue,w.CountOfWordMatch,m.MatchStartLen FROM @BaseTable b LEFT OUTER JOIN WordMatchCount w ON b.RowID=w.RowID LEFT OUTER JOIN MatchLen m ON b.RowID=m.RowID WHERE w.CountOfWordMatch>0 ORDER BY w.CountOfWordMatch DESC,m.MatchStartLen DESC,LEN(b.RowValue) DESC,b.RowValue ASC 

SORTIE:

 RowValue CountOfWordMatch MatchStartLen ----------------------------------------------------------------------- ---------------- ------------- This is my ssortingng as a test template to rank on. 11 11 This is my ssortingng as a test template to rank on even though not exact. 10 11 This is my ssortingng as a test template to rank 10 11 This is my ssortingng as a test template to 9 11 This is my ssortingng as a test template 8 11 (5 row(s) affected) 

Le début du mot de string correspond un peu différemment, en ce sens qu'il regarde le nombre de caractères du début de la string qui correspond.

Une fois que cela fonctionne, vous pouvez essayer de l'optimiser en créant des tables indexées statiques pour SplitBaseTable. Utilisez éventuellement un triggersur sur votre @BaseTable.

Il semble que vous cherchiez un algorithm correspondant, qui peut être difficile à créer sans l'utilisation de procédures stockées. De l'expérience passée, il existe des algorithms de distance d'édition (tels que Levenshtein) qui sont très utiles pour déterminer la similarité. Ceux-ci renvoient un nombre, parfois un certain nombre de différences entre les strings, sur lequel vous pouvez créer votre propre équation de pondération pour donner un score. Vous pouvez ensuite créer des classments ou des seuils pour les scores afin de réduire les faux négatifs / positifs.

J'ai eu une question similaire il y a quelques time. La question à laquelle j'essayais de répondre était de savoir combien de mots correspondaient entre deux colonnes différentes, et le rang basé sur le pourcentage le plus élevé de mots appariés. C'était bien au-delà de moi mais j'ai reçu une réponse fantastique de Martin.

Découvrez sa réponse à ma question ici .

Une réponse à tous vos problèmes: utilisez sphynx http://sphinxsearch.com et ne résolvez pas cela en SQL.

Sphynx est open source, fonctionne avec toutes les bases de données et tous les systèmes d'exploitation.

C'est ce que craigslist utilise.

C'est le meilleur système de search plein text en dehors de ce post. Il classra vos résultats dans la pertinence que vous requestz et vous n'aurez pas besoin de tables SQL sophistiquées ou de procédures SQL. Essayez-le.