我正在尝试在两个表上进行JOIN。每个表包含来自不同数据源的UPC varchar2(20)。
这个JOIN有点困难的原因是UPC的值大小不一,有时可以用前导零填充,有时不填充。所有都包含一个尾随校验位。
例如:
Table 1 Table 2
UPC "00000123456789" "123456789"
"234567890" "234567890"
"00000003456789" "00000003456789"
"3456799" "00000003456799"
我的想法是将每个转换为长,然后进行比较。或者我可以追加前导零。或者包含一个。
使用SQL进行连接的最佳方法是什么?
答案 0 :(得分:5)
你可以试试这个:
select * from
table1 inner join table2
on (CAST(CAST(table1.UPC AS BIGINT) AS VARCHAR))
=(CAST(CAST(table2.UPC AS BIGINT) AS VARCHAR))
<强> SQL FIDDLE DEMO 强>
或
select * from
table1 inner join table2
on (RIGHT(table1.UPC,(LEN(table1.UPC) - PATINDEX('%[^0]%',table1.UPC)) + 1))
=(RIGHT(table2.UPC,(LEN(table2.UPC) - PATINDEX('%[^0]%',table2.UPC)) + 1))
<强> SQL FIDDLE DEMO 强>
答案 1 :(得分:2)
这不是性能最高的选项,但它是最简单的选择:
SELECT
T1.UPC,
T2.Column1
FROM
myTable T1
INNER JOIN myTable T2 ON
RIGHT(REPLICATE('0', 20) + T2.UPC, 20) = RIGHT(REPLICATE('0', 20) + T1.UPC, 20)
或者,您可以为这些填充的UPC创建计算列,并在其上放置索引。但是,这带来了一系列限制。我无法在现实世界中多次使用它。
答案 2 :(得分:1)
如果您能够向表中添加列,则可以使用持久计算列将varchar转换为bigint。然后可以将它们编入索引,并且这些连接将更快。在那些读取比写入更多的应用程序中,这是值得的。
create table ack
(
UPC
varchar( 20 ) null,
UPCValue
as isnull( convert( bigint, Upc ), 0 ) persisted
)
如果Upc不需要支持null,则不必执行isnull。
答案 3 :(得分:0)
大多数UPC值为12位数,或者EAN变量为13位(参见http://en.m.wikipedia.org/wiki/Universal_Product_Code)。因此,如果您可以通过更改表来使列大小与最简单的预期值大小匹配。您可以将表更改为varchar(18)以允许5-6个前导零,同时仍允许将值安全地转换为bigint。 bigint的最大大小为9,223,372,036,854,775,807(19位),因此存储在varchar(18)中的任何数值都适合。然后您可以轻松查询:
Select *
From tab1
Join tab2
on cast (tab1.upc as bigint) = cast(tab2.upc as bigint);
如果您坚持使用varchar(20)列,则假设您的实际数据不包含超出bigint最大大小的错误值,则转换为bigint仍然有效。但显然这不是防弹的。例如,一串20个9('99999999999999999999')将导致数据截断。
如果你真的需要20个数字,你需要通过左边填充比较字符串或者修剪左边的零来比较字符串,如其他一些答案所示。