用于检查Field中多个拼写的SQL CASE语句,如果找到则返回相同的值?

时间:2015-04-15 16:14:31

标签: sql database oracle toad oracle12c

我正在创建一个Oracle数据库转换脚本,以便将记录从旧的单个表移动到具有更多字段的新表以及子/引用表,以获得更好的完整性。当我在Table1中为SELECT DISTINCT运行VENDOR时,我得到了58个结果。这些结果对于相同含义有多么不同的一个例子如下:

  • WWT
  • &安培; nbspWWT
  • Worldwide Technologies
  • & nbspWorldwide Technologies
  • WorldWide Technology
  • World Wide Technology

在我的参考表中,我已将此特定值的记录设置为"World Wide Technology, Inc."

有没有一种方法我可以指定(可能是一个CASE语句?)当这些不同的拼写用于返回我在子表中的值时(例如)"World Wide Technology, Inc."

这个表是最简单的子表,因为它只有17个不同的值插入其中,而Table1有58个不同的行返回。到目前为止,我有:

INSERT INTO Table2 (VendorID, col2, col3, col4, etc...)
SELECT T3.ID, T1.col7, T1.col8, T1.col9, etc...
FROM Table1 T1
INNER JOIN Table3 T3 ON LTRIM(UPPER(T1.Vendor)) = UPPER(T3.Vendor_Name)

我在Table1中获得了1349条记录,但是这(仅用于SELECT部分​​)只返回418条记录。

有谁知道我在这之后怎么回事?

2 个答案:

答案 0 :(得分:3)

如果您没有并且不想创建映射表,则案例方法与您之前关于日期的问题类似。要转换所有值,您需要执行以下操作:

select case
  when vendor in (
    'WWT',
    ' WWT',
    'Worldwide Technologies',
    ' Worldwide Technologies',
    ' WorldWide Technology',
    'World Wide Technology'
  ) then 'World Wide Technology, Inc.'
  when t1.vendor in (
    'ACME',
    ' acme'
  ) then 'ACME, Inc.'
  ... other groups of original values with their new equivalents
  else null
  end as vendor_name
from t1;

在您的情况下,您可能会对新vendor_id而不是名称进行硬编码,否则您只需加入t3即可根据您的映射名称获取ID:

INSERT INTO Table2 (VendorID, col2, col3, col4, etc...)
SELECT case
  when t1.vendor in (
    'WWT',
    ' WWT',
    'Worldwide Technologies',
    ' Worldwide Technologies',
    ' WorldWide Technology',
    'World Wide Technology'
  ) then 42 -- ID for 'World Wide Technology, Inc.'
  when t1.vendor in (
    'ACME',
    ' acme'
  ) then 76 -- ID for 'ACME, Inc.'
  ... other groups of original values with their new equivalents
  else null
  end as vendor_id, T1.col7, T1.col8, T1.col9, etc...
FROM Table1 T1;

如果你有很多不同的值,只有大小写和前导/尾随空格不同,你可以减少要检查的值的数量:

select case
  when trim(upper(t1.vendor)) in (
    'WWT',
    'WORLDWIDE TECHNOLOGIES',
    'WORLD WIDE TECHNOLOGY'
  ) then 42 -- ID for 'World Wide Technology, Inc.'
  when trim(upper(t1.vendor)) in (
    'ACME'
  ) then 76 -- ID for 'ACME, Inc.'
  else null
  end as vendor_name
from t1;

您可能还可能删除标点符号等。基本上,您用于识别第一个位置的不同值的查询表达式必须与您在案例表达式中使用的任何内容相匹配。因此,在这个示例中,不是原来的SELECT DISTINCT VENDOR FROM Table1得到58个值,而是SELECT DISTINCT TRIM(UPPER(VENDOR)) FROM Table1,这样可以减少,减少(轻微)手动将每个值与新供应商ID匹配的痛苦。

如果要在大小写映射中使用描述,可以加入新的查找表,然后在join子句中执行该操作:

select t1.vendor, t3.vendor_id, t3.description
from t1
left join t3 on t3.description = case
  when trim(upper(t1.vendor)) in (
    'WWT',
    'WORLDWIDE TECHNOLOGIES',
    'WORLD WIDE TECHNOLOGY'
  ) then 'World Wide Technology, Inc.'
  when trim(upper(t1.vendor)) in (
    'ACME'
  ) then 'ACME, Inc.'
  else null
  end;

VENDOR                    VENDOR_ID DESCRIPTION               
------------------------ ---------- ---------------------------
 Worldwide Technologies          42 World Wide Technology, Inc.
 World Wide Technology           42 World Wide Technology, Inc.
WWT                              42 World Wide Technology, Inc.
 AcMe                            76 ACME, Inc.                 

等。显然,这只是一个演示。我已经使它成为左连接,所以如果你有一个你没有映射的值,或者在描述中有拼写错误等,它会尝试插入一个空值。然后,您可以根据需要查找空值并填充它们,或者对新的(外键,可能)列具有无空约束,这样就不会让您在没有匹配的情况下插入 - 但这可能限制太多,再次取决于您的实际数据。

答案 1 :(得分:0)

我认为您正在寻找LEFT OUTER JOIN。然后假设您有一个映射表Table4,列wrong表示您想要的实体的拼写错误,right表示正确的拼写。然后:

INSERT INTO Table2 (VendorID, col2, col3, col4, etc...)
SELECT COALESCE ( T4.RIGHT, T3.ID, T1.Vendor ), T1.col7, T1.col8, T1.col9, etc...
FROM Table1 T1
LEFT OUTER JOIN Table3 T3 ON LTRIM(UPPER(T1.Vendor)) = UPPER(T3.Vendor_Name)
LEFT OUTER JOIN Table4 T4 ON LTRIM(UPPER(T1.Vendor)) = UPPER (T4.WRONG)

JOIN将包含来自T1的所有记录以及来自T3T4的结果,仅适用于JOIN中的匹配条件。如果不满足条件,则查询结果中的所有T3 / T4列都会显示为NULL。因此,您可以在COALESCE子句中使用SELECT来说明:如果有T4.right,请使用它,否则,如果有T3.ID,则使用它,否则,使用T1.Vendor