I am trying to build a case/if statement in a JOIN ON
clause.
LEFT JOIN [CTSTRC] [Statuses] ON RIGHT([Statuses].[STRID], 3) = [CTE].[F61]
Wouldn't something like this work:
LEFT JOIN [CTSTRC] [Statuses] ON RIGHT([Statuses].[STRID], 3) = cast([CTE].[F61] as varchar(3))
All you really care about is whether you have a match, so why not convert the numeric to varchar? You would have to test both ideas to see which one is faster.
I do agree with @KM, fixing a bad design like this is the best solution. Having functions and Case statements in a join is an indicatior that your design is fatally flawed and should be fixed.
You're looking for the ISNUMERIC function (I believe it was introduced in 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]
create a persisted computed column and add an index on it.
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
you can now just join to the new NewIntID column as if it were the proper numeric ID now.
You're looking for IsNumeric but it doesn't always work (+,- and . are numeric) so you need to use the solution described by GBN which is to add .0e0 to your 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]
You can try to create an expression column in the Statuses table that converts the right 3 characters to a number and then try to join on the expression column.
You might want to try something like this
select ...
from CTE
inner join
(
select ...
from [Statuses]
where ISNUMERIC(STRID + '.0e0') = 1
) rsNumeric on CTE.F61 = rsNumeric.STRID