JOIN ON子句中的T-SQL Case语句

时间:2011-12-02 18:55:18

标签: sql sql-server sql-server-2005 tsql

我正在尝试在JOIN ON子句中构建case / if语句。

LEFT JOIN [CTSTRC] [Statuses] ON RIGHT([Statuses].[STRID], 3) = [CTE].[F61]

问题是列[Statuses].[STRID]包含文本和数字。我将它与[CTE].[F61]进行比较的列是一个整数。

有没有办法检测列[Statuses].[STRID]是否有字符或数字?如果它是字符,那么将它设置为0?

这是一个帮助的伪查询:

LEFT JOIN [CTSTRC] [Statuses] ON RIGHT((CASE [Statuses].[STRID] WHEN TEXT THEN 0 ELSE CAST([Statuses].[STRID] AS INT) END), 3) = [CTE].[F61]

有人能指出我正确的方向吗?

谢谢!

6 个答案:

答案 0 :(得分:16)

您正在寻找IsNumeric,但它并不总是有用(+, - 和。是数字),因此您需要使用解决方案described by GBN将.0e0添加到您的varchar

LEFT JOIN [CTSTRC] [Statuses] ON 
    (CASE WHEN ISNUMERIC(RIGHT([Statuses].[STRID], 3) + '.0e0) = 1 
          THEN  CAST(RIGHT([Statuses].[STRID], 3) AS INT) 
          ELSE 0  END) = [CTE].[F61] 

答案 1 :(得分:4)

创建一个持久的计算列并在其上添加索引。

ALTER TABLE YourTable ADD
    NewIntID AS (CASE ISNUMERIC(RIGHT([Statuses].[STRID], 3) + '.0e0)
                     WHEN 1 THEN CAST(RIGHT([Statuses].[STRID], 3) AS INT) 
                     ELSE 0
                 END) PERSISTED
GO

CREATE INDEX IX_YourTable_NewIntID 
ON YourTable (NewIntID ); 
GO

您现在可以加入新的NewIntID列,就好像它现在是正确的数字ID一样。

答案 2 :(得分:3)

您可以尝试在Statuses表中创建一个表达式列,将右侧3个字符转换为数字,然后尝试连接表达式列。

答案 3 :(得分:1)

不会像这样的工作:

LEFT JOIN [CTSTRC] [Statuses] ON RIGHT([Statuses].[STRID], 3) = cast([CTE].[F61] as varchar(3))

您真正关心的是您是否匹配,那么为什么不将数字转换为varchar?你必须测试这两个想法,看看哪一个更快。

我同意@KM,修复这样糟糕的设计是最好的解决方案。在连接中使用函数和Case语句表明您的设计存在致命缺陷且应该修复。

答案 4 :(得分:0)

您正在寻找ISNUMERIC函数(我相信它是在SQL 2005中引入的):

LEFT JOIN [CTSTRC] [Statuses] ON 
    (CASE ISNUMERIC(RIGHT([Statuses].[STRID], 3)) WHEN 0 THEN 0 ELSE CAST(RIGHT([Statuses].[STRID], 3) AS INT) END) = [CTE].[F61] 

答案 5 :(得分:0)

你可能想尝试这样的事情

select ...
from CTE
inner join
(
    select ...
    from [Statuses]
    where ISNUMERIC(STRID + '.0e0') = 1
) rsNumeric on CTE.F61 = rsNumeric.STRID