Нечеткое совпадение на строке - PullRequest
1 голос
/ 20 апреля 2011

У меня есть вопрос, связанный с соответствующими строками в базе данных MSSQL.По сути, у меня есть таблица, которая содержит коды ICD9 и CPT.Проблема заключается в том, что формат, в котором вводятся эти коды, обычно неверен (т. Е. Слишком много символов, отсутствует десятичная дробь и т. Д.).Мне нужно иметь возможность искать описание для каждого из этих кодов в справочной таблице, содержащей правильный код.

Из-за структуры этих кодов я могу выполнить какое-то «прогрессивное» соответствие, по крайней мере,найдите категорию кода.

Допустим, правильный код выглядит примерно так: 306.98

И для этого примера давайте представим, что нет других значений между 306 и 307.

Я хотел бы убрать десятичную дробь и искать совпадения, по одному символу за раз, пока один не будет найден.Затем выберите последнюю подходящую строку.

Так что 306,3069,3098, 306981, 3069812 и т. Д. ... будет соответствовать строке 306,98.

Надеюсь, это имеет смысл для всех.Я не уверен, как я мог бы начать это делать, поэтому любое предложение было бы очень полезным.

Ответы [ 4 ]

1 голос
/ 20 апреля 2011

Используйте функцию FLOOR для удаления десятичной части, а затем используйте оператор LIKE в предложении WHERE.

Что-то вроде:

SELECT <COLUMN-LIST>
  FROM <TABLE-NAME>
 WHERE <THE-COLUMN> LIKE CAST(FLOOR(306.09) AS VARCHAR) + '%'
1 голос
/ 20 апреля 2011

Одним из возможных решений является сокращение кода до его базового элемента (306) и затем выполнение оператора like:

WHERE Code LIKE '306%'
0 голосов
/ 12 мая 2011

Я смог понять это. По сути, мне просто нужно было пройтись по каждому символу строки и искать совпадение, пока один раз больше не был найден. Спасибо за помощь!

/* ICD9 Lookup */

USE TSiData_Suite_LWHS_V11

DECLARE @String NVARCHAR (10)
DECLARE @Match NVARCHAR(10)
DECLARE @Substring NVARCHAR (10)
DECLARE @Description NVARCHAR(MAX) 
DECLARE @Length INT
DECLARE @Count INT

SET @String = '309.99999999'

/* Remove decimal place from string */
SET @String = REPLACE(@String,'.','')

/* Get lenth of string */
SET @Length = LEN(@String)

/* Initialize count */
SET @Count = 1

/* Get Substring */
SET @Substring = SUBSTRING(@String,1,@Count)

/* Start processing */
IF (@Length < 1 OR @String IS NULL)
    /* Validate @String */
    BEGIN

        SET @Description = 'No match found for string. String is not proper length.'

    END
ELSE IF ((SELECT COUNT(*) FROM LookupDiseases WHERE REPLACE(LookupCodeDesc,'.','') LIKE @Substring + '%') < 1)
    /* Check for at least one match */
    BEGIN

        SET @Description = 'No match found for string.'

    END
ELSE
    /* Look for matching code */
    BEGIN

        WHILE ((SELECT COUNT(*) FROM ICD9Lookup WHERE REPLACE(LookupCodeDesc,'.','') LIKE @Substring + '%') <> 1 AND (@Count < @Length + 1))
        BEGIN

            /* Update substring value */
            SET @Substring = SUBSTRING(@String,1,@Count + 1)

            /* Increment @Count */
            SET @Count += 1

            /* Select the first matching code and get description */
            SELECT TOP(1) @Match =  LookupCodeDesc, @Description = LookupName FROM ICD9Lookup WHERE REPLACE(LookupCodeDesc,'.','') LIKE @Substring + '%' ORDER BY LookupCodeDesc ASC

        END
    END

PRINT @Match
PRINT @Description
0 голосов
/ 20 апреля 2011

Вот ваш пример. Вам просто нужно преобразовать значение в nvarchar @ string.

DECLARE @string AS NVARCHAR (MAX) = '306.98';
DECLARE @Table TABLE (
    TextVal NVARCHAR (MAX));

INSERT INTO @Table ([TextVal])
SELECT '4444656'
UNION ALL
SELECT '30'
UNION ALL
SELECT '3069'
UNION ALL
SELECT '306989878787'
;

WITH   numbers
AS     (SELECT ROW_NUMBER() OVER ( ORDER BY (SELECT 1)) AS Number
        FROM   [sys].[objects] AS o1 CROSS JOIN [sys].[objects] AS o2),
       Chars
AS     (SELECT SUBSTRING(@string, [Number], 1) AS Let,
               [Number]
        FROM   [numbers]
        WHERE  [Number] <= LEN(@string)),
       Joined
AS     (SELECT [Let],
               CAST (1 AS BIGINT) AS Number
        FROM   chars
        WHERE  [Number] = 1
        UNION ALL
        SELECT [J].[Let] + CASE 
                           WHEN [Chars].[Let] = '.' THEN '' ELSE [Chars].[Let] 
                           END AS LEt,
               Chars.[Number]
        FROM   [Joined] AS J
               INNER JOIN
               [Chars]
               ON [Chars].[Number] = [J].[Number] + 1)
SELECT *
FROM   @Table AS T
WHERE  [T].[TextVal] IN (SELECT [Let]
                         FROM   [Joined])
          OR [T].[TextVal] LIKE '%'+(SELECT TOP 1 [Let] FROM
          [Joined] ORDER BY [Number] DESC )  +'%'            
                         ;

Результат будет:

 TextVal
30
3069
306989878787
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...