【问题标题】:How to join two table with partial match如何连接两个部分匹配的表
【发布时间】:2013-12-23 02:41:15
【问题描述】:

我有两个包含以下数据的表:

TableA.name
R4.23-Core-2
R4.23-Core-2
LA#213 CGHPBXsw01 127.213 0024-737e-e341
LA#252 CGHRack1sw01 127.252 0022-57ab-d781
SOC-01A-SW01
to - R4-DISTR-9512
to-R2-DISTR-5900-1
to-R3.25-EDGE

TableB.caption
R4.23-Core-2.ehd.ca
R4.23-Core-2.nhd.ca
CGHPBXsw01
CGHRack1sw01
SOC-01A-SW01
R4-DISTR-9512
R2-DISTR-5900-1.phsnc.
R3.25-EDGE.phsne.edjc.ca

我已经尝试使用以下 join 语句,但它似乎不适用于任何带有 .在里面。

dbo.TableA.Name 
INNER JOIN dbo.TableB.Caption 
  ON dbo.TableA.Name LIKE '%' + dbo.TableB.Caption + '%'

我也尝试使用替换功能,该功能有效,但替换包含的变体太多。

我可以尝试使用 RIGHT 或 LEFT 函数来规范化数据,但对于没有“。”的行它会抛出一个错误。而且我不知道如何跳过没有'.'的行

连接这两个表最有效的方法是什么?

【问题讨论】:

  • 该连接应该可以工作。 TableA 中的哪个项目与 TableB 中的具体不匹配?
  • 为什么不添加一个带有某种 id 的列并加入它。
  • @user3072241 如果我理解正确,您是在尝试将 A 中的行与 B 中的行连接起来,其中 B 中的 Caption 列完全包含在 A 的 Name 列中?无论如何,这就是您的联接表达式所说的。我在 SQL Fiddle (SQL Server 2012) 中尝试了这个,它可以按我的预期工作。您使用的是不同的数据库吗?
  • 好吧,您加入的是表而不是列,因此您至少必须将其更改为 dbo.TableA INNER JOIN dbo.TableB,然后指定您的加入条件。
  • join 语句有效,但它会省略所有具有 '.' 的行例如 (R4.23-Core-2.nhd.ca)

标签: sql join replace


【解决方案1】:

这个怎么样(未测试)

dbo.TableA
INNER JOIN dbo.TableB 
      ON CHARINDEX(dbo.TableB.Caption, dbo.TableA.Name) > 0

测试它,不要忘记支持或接受。

【讨论】:

    【解决方案2】:

    在您的示例中的某些情况下,标题较长,而在其他情况下,名称较长,如果您想加入任何名称在标题中或标题在您可以使用的名称中的值:

    dbo.TableA.Name 
    INNER JOIN dbo.TableB.Caption 
       ON   dbo.TableA.Name LIKE '%' + dbo.TableB.Caption + '%'
         OR dbo.TableB.Caption LIKE '%' + dbo.TableA.Name + '%'
    

    这可以解释为什么您的查询没有按预期工作。

    就执行此操作的最有效方法而言,您希望在表中有一个标准化字段,您可以通过相等性将其用于JOIN(例如 a.col1 = b.col1),所以这将需要剥离使其值得加入的每个领域的核心。

    更新:如果重要部分是第一个句点之前的所有内容,那么您想使用 LEFT()CHARINDEX() 的组合(以及 CASE 语句,因为并非所有字符串都包含句点):

    SELECT NewField = CASE WHEN CHARINDEX('.',Name) > 0 THEN  LEFT(Name,CHARINDEX('.',Name)-1) 
                           ELSE Name
                      END
    FROM YourTable  
    

    您也可以在 JOIN 中使用上述内容:

    dbo.TableA.Name 
    INNER JOIN dbo.TableB.Caption 
      ON CASE WHEN CHARINDEX('.',TableA.Name) > 0 THEN  LEFT(TableA.Name,CHARINDEX('.',TableA.Name)-1) 
                               ELSE TableA.Name
                          END
        = CASE WHEN CHARINDEX('.',TableB.Caption) > 0 THEN  LEFT(TableB.Caption,CHARINDEX('.',TableB.Caption)-1) 
                               ELSE TableB.Caption
                          END
    

    【讨论】:

    • 我确实想对此进行标准化并尝试使用 RIGHT 函数:
    • 你能描述一下字段值的哪一部分是重要的部分吗?
    • 所以我尝试标准化 TableB TableB.caption R4.23-Core-2.ehd.ca R4.23-Core-2.nhd.ca CGHPBXsw01 CGHRack1sw01 SOC-01A-SW01 R4-DISTR- 9512 R2-DISTR-5900-1.phsnc。 R3.25-EDGE.phsne.edjc.ca using LEFT (dbo.TableB.Caption, CHARINDEX('.', dbo.TableB.Caption) - 1) 但是当它到达任何没有'。'例如 CGHPBXsw01 我知道通过此错误的唯一方法是使用 NULLIF 但这会将 NULL 返回到该行而不是实际的行值
    • 重要的部分是第一个'.'之前的所有内容
    • 那个case语句完美的工作!!!可以做巢箱吗?如果我有一些 IP 格式的行?像 10.1.1.1
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-01-05
    • 1970-01-01
    • 2015-08-24
    • 1970-01-01
    • 1970-01-01
    • 2011-09-24
    相关资源
    最近更新 更多