在产品UPC varchar(20)上加入的最佳方式?

时间:2015-05-08 18:07:04

标签: sql sql-server

我正在尝试在两个表上进行JOIN。每个表包含来自不同数据源的UPC varchar2(20)。

这个JOIN有点困难的原因是UPC的值大小不一,有时可以用前导零填充,有时不填充。所有都包含一个尾随校验位。

例如:

        Table 1               Table 2
UPC     "00000123456789"           "123456789"
             "234567890"           "234567890"
        "00000003456789"      "00000003456789"
               "3456799"      "00000003456799"

我的想法是将每个转换为长,然后进行比较。或者我可以追加前导零。或者包含一个。

使用SQL进行连接的最佳方法是什么?

4 个答案:

答案 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创建计算列,并在其上放置索引。但是,这带来了一系列限制。我无法在现实世界中多次使用它。

Indexes on Computed Columns (MSFT)

答案 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个数字,你需要通过左边填充比较字符串或者修剪左边的零来比较字符串,如其他一些答案所示。