【问题标题】:SQL comparing similar columnsSQL比较相似的列
【发布时间】:2013-11-19 19:30:38
【问题描述】:

我有两列可能包含相似的数据,我正在尝试找出如何比较两者的相似性。

TABLE:
PatientID | InsurnaceCompany1 | InsuranceCompany2
111111111 | Medicaid          | Medicaid - Part D
222222222 | Medicaid - ABC Co | Medicaid
333333333 | Medicaid - ABC Co | Medicaid - Part D
444444444 | MVP Insurance     | MVP
555555555 | Medicare          | Medicaid
666666666 | Medicaid          | MVP
777777777 | Private - MVP     | MVP Option

问题是, 如何比较两列以了解它们是否相似。

结果应该是这样的:

PatientID | InsurnaceCompany1 | InsuranceCompany2 | Result
111111111 | Medicaid          | Medicaid - Part D | TRUE
222222222 | Medicaid - ABC Co | Medicaid          | TRUE
333333333 | Medicaid - ABC Co | Medicaid - Part D | TRUE
444444444 | MVP Insurance     | MVP               | TRUE
555555555 | Medicare          | Medicaid          | FALSE
666666666 | Medicaid          | MVP               | FALSE
777777777 | Private - MVP     | MVP Option        | TRUE

我可以使用 case 语句来检查其中的几个选项,例如:

case
    when InsuranceCompany1 like '%' + InsuranceCompany2 + '%' then 'TRUE'
    when InsuranceCompany2 like '%' + InsuranceCompany1 + '%' then 'TRUE'
    else 'FALSE'
end AS Result

但对于上述 PatientID 333333333 和 777777777,此测试失败。

为了澄清起见,我将“相似”定义如下:如果两个术语都包含相同的词,则它们是相似的。即使这个词是通用词(例如“insurance”)也适用。因此,“Insurance Company B”与“Insurance Company A”相似,原因有两个:“Insurance”和“Company”。

【问题讨论】:

  • 你如何定义“相似”?
  • 如果第一个保险公司的任何部分(单词)在第二个保险公司中,反之亦然。即:如果“医疗补助”出现在两列的某处,那么它们是相似的。同样,如果“MVP”出现在两列中的某处,那么它们是相似的。
  • 如果“保险”出现在两列怎么办?
  • 如果没有存储过程,我不知道该怎么做。
  • 如果“保险”出现在两者中,我会接受正确的答案。理想情况下不会,但对我来说是可以接受的。

标签: sql case string-comparison


【解决方案1】:

我认为您的问题中隐含了很多特定领域的知识(关于“相似”名称的确切构成),您无法通过通用比较来解决这个问题。您最好的选择可能是在查询中列举您的具体要求,这样您就可以准确控制您得到的内容:

select
  *
from
  patients
where
  InsuranceCompany1 like concat('%', InsuranceCompany2, '%') or 
  InsuranceCompany2 like concat('%', InsuranceCompany1, '%') or
  (InsuranceCompany1 like '%medicaid%' and InsuranceCompany2 like '%medicaid%') or
  (InsuranceCompany1 like '%medicare%' and InsuranceCompany2 like '%medicare%') or
  (InsuranceCompany1 like '%mvp%' and InsuranceCompany2 like '%mvp%') or
  ...etc...

http://sqlfiddle.com/#!2/9de7b/13

【讨论】:

  • 这行不通,不幸的是,如果出现新的东西(比如新的保险公司),因为它将被硬编码到逻辑中
  • 不开玩笑,但最初对“相似性”的要求是如此模糊,以至于它是解决它的唯一实用方法。您可以拼凑一个基于单词的解析器,当一个字段中的任何单词与另一个字段中的任何单词匹配时,它会给您一个肯定的结果,但是当您获得拥有“North Fairfield Insurance”和“South Fairfield”的患者时,这仍然会失败保险”。
  • 我认为“North Fairfield Insurance”和“South Fairfield Insurance”相似,因为它们的名称中包含“Farifield”和“insurance”。
  • 好的。不过,我想我真的不明白这一点。在任何情况下,您都会遇到困难,因为 SQL 并不是特别擅长字符串解析。您可以使用诸如 locate() 和 substr() 之类的函数进行一些基本的解析,但是对于具有可变字数的字符串来说,这将变得很难看。而且我仍然认为你最终会得到一堆特殊用途的逻辑,除非你对你的 if-any-word-matches-then-they-are-similar 逻辑将有“Medicaid - Part D”类似于“Joe Part & Sons Insurance”。
  • 也许最好更笼统地考虑这一点:Table:ID | FieldA | FieldB | HasCommonWord
【解决方案2】:

编辑

DECLARE @t TABLE (PatientID INT, InsurnaceCompany1 NVARCHAR(50), InsuranceCompany2 NVARCHAR(50))

INSERT INTO @t 
VALUES 
(111111111,'Medicaid'          ,'Medicaid - Part D'),
(222222222,'Medicaid - ABC Co' ,'Medicaid'),
(333333333,'Medicaid - ABC Co'  ,'Medicaid - Part D'),
(444444444,'MVP Insurance'      ,'MVP'),
(555555555,'Medicare'           ,'Medicaid'),
(666666666,'Medicaid'           ,'MVP'),
(777777777,'Private - MVP'      ,'MVP Option')


SELECT PatientID, InsurnaceCompany1, InsuranceCompany2 ,
    CASE WHEN LEFT(InsurnaceCompany1,CASE WHEN CHARINDEX(' ', InsurnaceCompany1) = 0 
                    THEN LEN(InsurnaceCompany1) ELSE CHARINDEX(' ', InsurnaceCompany1) END ) 
            = LEFT(InsuranceCompany2,CASE WHEN CHARINDEX(' ', InsuranceCompany2) = 0 
                THEN LEN(InsuranceCompany2) ELSE CHARINDEX(' ', InsuranceCompany2) END ) 
                THEN 'TRUE' ELSE 'FALSE' END    AS RESULT 
FROM @t

结果集

PatientID   InsurnaceCompany1   InsuranceCompany2   RESULT
111111111   Medicaid            Medicaid - Part D   TRUE
222222222   Medicaid - ABC Co   Medicaid            TRUE
333333333   Medicaid - ABC Co   Medicaid - Part D   TRUE
444444444   MVP Insurance       MVP                 TRUE
555555555   Medicare            Medicaid            FALSE
666666666   Medicaid            MVP                 FALSE
777777777   Private - MVP       MVP Option          FALSE

【讨论】:

  • 我很困惑...不是说任何一列都可以吗? InsurnaceCompany1 like '%'
  • InsuranceCompany1 like '%' + InsuranceCompany2 + '%' 有问题不会返回 True 或 False。
  • 使用 AND 或 OR 而不是 + 实际上会在 WHEN 子句中产生 True/False,然后用户可以返回 THEN 子句中提到的任何内容。在这种情况下,字符串 'True' 或 'False'
  • 通过这样做,所有答案都等同于真实......sqlfiddle.com/#!2/c9c28/6/0我认为这不是 OP 想要的......?
  • @user623952 现在看看,但 OP 的术语“相似”更像是一个人类术语,难以与 T-Sql 互操作,需要更精确什么是“相似”。
猜你喜欢
  • 2012-12-26
  • 2011-04-11
  • 1970-01-01
  • 1970-01-01
  • 2022-06-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多