将varchar转换为int,如果错误则返回原始值?

时间:2013-07-18 07:33:02

标签: sql-server exception casting

例如,我有两个表,如:

表1:

Column1
0001
0002
000a

表2:

Column2
0001
0002
000a

Column1和Column2的数据类型都是varchar(10)。 我必须一起加入2个表,所以我的查询应该是

Select * from Table1 join Table2 on Table1.Column1 = Table2.Column2

但是,正如我们所知,varchar类型中的join 2表比数字类型中的join 2表慢得多(我的表有数百万行)。我想一下尝试

Select * from Table1 join Table2 on Cast(Table1.Column1 as int) = 
Cast(Table2.Column2 as int)

通常情况下,它运行良好且速度更快。但如果我在第3行(000a)中遇到异常,我的查询将被破坏。所以,我想找一个像这样的查询:

Select * from Table1 join Table2 on
try
    Cast(Table1.Column1 as int) = Cast(Table2.Column2 as int)
catch if exception then
    Table1.Column1 = Table2.Column2

更新:--------------------------------------------- ---------------------------------------

我有一个理想:

首先,使用try_cast选择任何数字数据行:

select * from Table1 t1
join Table2 t2 
on try_cast(t1.Column1 as bigint) =try_cast(t2.Column2 as bigint)

之后,选择try_cast将变为null(异常行)的任何行:

select * from 
(select * from Table1 t1 where try_cast(t1.Column1 as bigint) is NULL and 
t1.Column1 is not NULL) as table1
join
(select * from Table2 t2 where try_cast(t2.Column2 as bigint) is NULL and 
t2.Column2 is not NULL) as table2
on table1.Column1=table2.Column2

最后将所有2个结果结合起来,我会得到我想要的东西。我接受测试,速度非常快。我的理想或我遗忘的东西有什么问题,请告诉我!

1 个答案:

答案 0 :(得分:0)

如果你想使用整数加入,在某些编码下有快速的方法,但你必须知道你的数据:将你的值转换为数字。获取数字的想法是这样的:

SELECT Column1,
   ASCII(SUBSTRING(c1, 1, 1)) * 256 * 256 * 256
 + ASCII(SUBSTRING(c1, 2, 1)) * 256 * 256
 + ASCII(SUBSTRING(c1, 3, 1)) * 256 
 + ASCII(SUBSTRING(c1, 4, 1)) AS Column1Num
FROM Table1

结果:

Column1    Column1Num
---------- -----------
0001       808464433
0002       808464434
000a       808464481

这坚持你的所有值为4个字符长的例子。关键是找到表达式,该表达式为每个唯一值创建唯一编号,并且仍适用于您的所有记录。然后将此表达式用作JOIN的键。

  • 如果不是所有值都具有相同的长度,则可以对其进行补偿(例如,通过SPACE()函数)
  • 如果您的数字实际上是十六进制(0123456789abcdef),那么在应用商数之前将每个数字转换为值0..15之后,您可以将商数从256减少到16
  • 这只是为了向您展示替代方法 - 知道您的数据可以显示最佳计算公式,但也可以证明无法进行此类计算

主要提示:评估所有方法的性能( [1] 加入varchars, [2] 方法来自您的问题更新, [3] 这个答案建议的方法)并选择最快的