【问题标题】:How to get almost matching string from Oracle table?如何从 Oracle 表中获取几乎匹配的字符串?
【发布时间】:2015-07-08 05:23:15
【问题描述】:

我在 Oracle 中有一个包含四列的表。

现在用户可以在我的查询中输入输入字符串“右膝操作”(这是有效的),我的查询应该返回与 DiagnosisName 列中大部分单词匹配的 ICD 代码 (IKR123)。

以下是我当前的查询。(没有给出正确的输出)

SELECT diagnosisname
FROM
  (SELECT diagnosisname,
    UTL_MATCH.jaro_winkler_similarity('%operation Knee right%',diagnosisname)
  FROM icd_code
  ORDER BY UTL_MATCH.EDIT_DISTANCE_SIMILARITY('%operation Knee right%',diagnosisname) DESC
  )
WHERE ROWNUM<2;

这个查询给我的输出是“左膝手术”,但我的期望是“右膝手术”。

【问题讨论】:

    标签: sql oracle string-matching utl-match


    【解决方案1】:

    请试试这个查询。这可能有助于解决您的问题。

    SELECT diagnosisname 
       FROM (SELECT diagnosisname, UTL_MATCH.jaro_winkler_similarity('%operation Knee right%',diagnosisname) 
       FROM icd_code 
       WHERE UTL_MATCH.jaro_winkler_similarity('%operation Knee right%',diagnosisname) = 100
       ORDER BY UTL_MATCH.EDIT_DISTANCE_SIMILARITY('%operation Knee right%',diagnosisname) DESC) 
    WHERE ROWNUM<2
    

    【讨论】:

    • 你好@Pankaj,你正在比较 UTL_MATCH.jaro_winkler_similarity('%operation Knee right%',diagnosisname) = 100 这意味着第一个字符串和第二个字符串都应该完全匹配。但是我的要求是,即使它部分(但几乎)匹配也应该有效。
      但是您的查询什么也没返回。
    【解决方案2】:

    关于UTL_MATCH的使用有几点需要注意:

    • EDIT_DISTANCE_SIMILARITY:返回 0 到 100 之间的整数,其中 0 表示完全不相似,100 表示完全匹配。
    • JARO_WINKLER_SIMILARITY:返回 0 到 100 之间的整数,其中 0 表示完全不相似,100 表示完全匹配,但会尝试考虑可能的数据输入错误。

    ORDER BY UTL_MATCH.EDIT_DISTANCE_SIMILARITY('%operation Knee right%',diagnosisname) DESC

    这不会给你正确的结果。因为,您只考虑可能的相似性,而没有考虑数据输入错误。因此,您必须使用 JARO_WINKLER_SIMILARITY

    右膝手术

    您需要记住输入的 CASE 和要比较的列值。它们必须在相似的情况下才能正确匹配。您在 LOWERCASE 中传递输入,但是,您的列值在 INITCAP 中。更好地将列值和输入转换为类似的情况。

    我们看下面的演示来了解一下:

    SQL> WITH DATA AS(
      2  SELECT 'Heart Operation' diagnosis_name, 'IH123' icd_code FROM dual UNION ALL
      3  SELECT 'Knee Operation' diagnosis_name, 'IK123' icd_code FROM dual UNION ALL
      4  SELECT 'Left Knee Operation' diagnosis_name, 'IKL123' icd_code FROM dual UNION ALL
      5  SELECT 'Right Knee Operation' diagnosis_name, 'IKR123' icd_code FROM dual UNION ALL
      6  SELECT 'Fever' diagnosis_name, 'IF123' icd_code FROM dual
      7  )
      8  SELECT t.*,
      9    utl_match.edit_distance_similarity(upper(diagnosis_name),upper('operation Knee right')) eds,
     10    UTL_MATCH.jaro_winkler_similarity (upper(diagnosis_name),upper('operation Knee right')) jws
     11  FROM DATA t
     12  ORDER BY jws DESC
     13  /
    
    DIAGNOSIS_NAME       ICD_CO        EDS        JWS
    -------------------- ------ ---------- ----------
    Right Knee Operation IKR123         20         72
    Knee Operation       IK123          20         70
    Heart Operation      IH123          25         68
    Left Knee Operation  IKL123         25         64
    Fever                IF123          15         47
    
    SQL>
    

    因此,您会看到两者之间的不同之处。 jaro_winkler_similarity 在识别数据输入错误和提供最接近的匹配方面做得更好。在此基础上,只需将第一行按降序排序即可:

    SQL> WITH DATA AS(
      2  SELECT 'Heart Operation' diagnosis_name, 'IH123' icd_code FROM dual UNION ALL
      3  SELECT 'Knee Operation' diagnosis_name, 'IK123' icd_code FROM dual UNION ALL
      4  SELECT 'Left Knee Operation' diagnosis_name, 'IKL123' icd_code FROM dual UNION ALL
      5  SELECT 'Right Knee Operation' diagnosis_name, 'IKR123' icd_code FROM dual UNION ALL
      6  SELECT 'Fever' diagnosis_name, 'IF123' icd_code FROM dual
      7  )
      8  SELECT diagnosis_name
      9  FROM
     10    (SELECT t.*,
     11      utl_match.edit_distance_similarity(upper(diagnosis_name),upper('operation Knee right')) eds,
     12      UTL_MATCH.jaro_winkler_similarity (upper(diagnosis_name),upper('operation Knee right')) jws
     13    FROM DATA t
     14    ORDER BY jws DESC
     15    )
     16  WHERE rownum = 1
     17  /
    
    DIAGNOSIS_NAME
    --------------------
    Right Knee Operation
    
    SQL>
    

    【讨论】:

    • 嗨@Lalit,您的查询工作正常,但用户也可以输入 operation crime rt 而不是 operation crime right。左=lt,右=lt等,
    • @shary.sharath 您可以使用DECODE 自定义一些东西。该功能为您提供最接近的匹配,但很少有超出该功能范围的内容。您需要显式编写查询来处理可能存在歧义的情况。例如,operation knee rt 将给出两行,因为两者都是紧密匹配的。但是,如果您将rt 解码为right 并将lt 解码为left,您将获得所需的输出。请将其标记为已回答。
    • 您好@Lalit,我使用了您的查询SELECT diagnosisname FROM ( SELECT diagnosisname,utl_match.edit_distance_similarity(UPPER(diagnosisname),UPPER('knee operation Left ')) eds, UTL_MATCH.jaro_winkler_similarity (UPPER(diagnosisname),UPPER('knee operation Left ')) jws FROM icd_code ORDER BY jws DESC ) WHERE ROWNUM = 1,但它返回的是膝盖操作而不是左膝盖操作。我现在该怎么办?
    • 嗯,那是因为Knee Operation 与前两个词完美匹配。让我给你一个解决方法,同时你可以试试这个lalitkumarb.wordpress.com/2014/12/02/…你可以将字符串拆分为单个单词并使用IN运算符进行比较。
    • 对于句子中的单词匹配 jaro 或编辑哪个会更好?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-08-16
    • 1970-01-01
    • 1970-01-01
    • 2015-10-14
    • 1970-01-01
    相关资源
    最近更新 更多