我正在创建一个Oracle数据库转换脚本,以便将记录从旧的单个表移动到具有更多字段的新表以及子/引用表,以获得更好的完整性。当我在Table1中为SELECT DISTINCT
运行VENDOR
时,我得到了58个结果。这些结果对于相同含义有多么不同的一个例子如下:
在我的参考表中,我已将此特定值的记录设置为"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条记录。
有谁知道我在这之后怎么回事?
答案 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
的所有记录以及来自T3
或T4
的结果,仅适用于JOIN
中的匹配条件。如果不满足条件,则查询结果中的所有T3
/ T4
列都会显示为NULL
。因此,您可以在COALESCE
子句中使用SELECT
来说明:如果有T4.right
,请使用它,否则,如果有T3.ID
,则使用它,否则,使用T1.Vendor
。