2011-04-20 92 views
1

我有一個問題與在MSSQL數據庫中匹配字符串有關。基本上,我有一個包含ICD9和CPT代碼的表格。問題是這些代碼的格式通常是不正確的(即字符太多,缺少小數等等)。我需要能夠從包含正確代碼的查找表中查找每個代碼的描述。字符串上的模糊匹配

由於這些代碼結構的方式,我可以做一些類型的「漸進式」匹配,至少可以找到代碼的類別。

比方說,正確的代碼是一樣的東西:306.98

而且在這個例子中可以假裝有306和307

之間沒有其他的值,我想剝離十進制和尋找匹配,一次一個字符,直到找不到一個字符。然後選擇最後一個匹配字符串。

因此,306,3069,3098,306981,3069812等將匹配字符串306.98。

我希望對每個人都有意義。我不知道我怎麼會開始這樣做,所以任何建議都會有很大的幫助。

+0

你可以使用像句子 – 2011-04-20 12:44:54

+0

我不認爲轉換爲字符串並使用模糊匹配將幫助很多監守的字符串是如此之短 - 如果你有相匹配的desriptions會是更好的工具。 – DKnight 2011-04-20 19:29:53

+0

ICD9代碼和CPT代碼是否混合在一起? – DKnight 2011-04-20 19:30:30

回答

0

我能弄明白。基本上,我只需要遍歷字符串的每個字符並尋找匹配,直到找不到一個字符。謝謝您的幫助!

/* 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 
1

一種可能的解決方案是將代碼剝離下來到它的基本元件(306),然後執行一個類似操作:

WHERE Code LIKE '306%' 
+1

我認爲,但可能會有一個306.1,306.2,306.3 ...我想要一個30611的字符串匹配306.1和30621匹配306.2。那有意義嗎? – Matt 2011-04-20 12:54:02

+0

好吧,如同我所說的那樣,將它剝離爲「306」,然後使用「LIKE」。 – Aliostad 2011-04-20 12:57:36

+0

好的,是否有可能做到相反?先說3069812或30690,然後讓它匹配306.69。我假設它必須一次搜索1個字符,直到找不到匹配,然後選擇最後一個匹配值。 – Matt 2011-04-20 13:07:33

1

使用FLOOR函數來剝離小數部分,然後在使用LIKE操作者WHERE子句。

喜歡的東西:

SELECT <COLUMN-LIST> 
    FROM <TABLE-NAME> 
WHERE <THE-COLUMN> LIKE CAST(FLOOR(306.09) AS VARCHAR) + '%' 
+0

如果他有額外的字符和缺少小數位,我不認爲''LIKE'會足夠準確 – DKnight 2011-04-20 19:35:13

+0

@DKnight:是的,你說得對,但我們都不知道OP處理什麼樣的數據。因此任何可能的情況都是一個假設。 – Chandu 2011-04-20 19:37:43

+0

不幸的是,我熟悉ICD9代碼,他的描述指出缺少字符和小數位是他的主要問題。我認爲唯一真正的解決方案是儘可能推動更好的數據。醫療和賬單代碼不匹配可能是非常危險的,最好不要做出任何猜測。 – DKnight 2011-04-20 19:46:17

0

這裏,你有你的example.You只需要轉換價值爲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