I\'ve been given the task at work of creating a report based on a very poorly designed table structure.
Consider the following two tables. They contain techniques t
Using this function
Create FUNCTION F_SplitAsIntTable
(
@txt varchar(max)
)
RETURNS
@tab TABLE
(
ID int
)
AS
BEGIN
declare @i int
declare @s varchar(20)
Set @i = CHARINDEX(',',@txt)
While @i>1
begin
set @s = LEFT(@txt,@i-1)
insert into @tab (id) values (@s)
Set @txt=RIGHT(@txt,Len(@txt)-@i)
Set @i = CHARINDEX(',',@txt)
end
insert into @tab (id) values (@txt)
RETURN
END
You can query like this
declare @a Table (id int,Name varchar(10),Kind Varchar(100))
insert into @a values (1,'test','1,2,3,4'),(2,'test2','1,2,3,5'),(3,'test3','3,5')
Select a.ID,Name
from @a a
cross apply F_SplitAsIntTable(a.Kind) b
where b.ID=2
I think this query looks cleaner:
SELECT p.*,
t.Technique as ParsedTechnique
FROM Personnel p
JOIN Techniques t
ON CHARINDEX((','+CAST(t.id as varchar(10))+','), (','+p.technique+',')) > 0
WHERE t.id ='1';
You can just change the WHERE t.id =
to whatever TechniqueId
you need.
Fiddle Here
The first comment under the question provided the link to the answer. Here's what I ended up going with:
WHERE
p.Technique LIKE '%,29,%' --middle
OR
p.Technique LIKE '29,%' --start
OR
p.Technique LIKE '%,29' --end
OR
p.Technique = '29' --single (good point by Cheran S in comment)
At initial glance I thought it wouldn't work, but clever use of % made it not match ids like 129, etc.
One of the problems you have to prevent is prevent "1" from matching "10" and "11". For this, you want to be sure that all values are delimited by the separator (in this case a comma).
Here is a method using like
that should work effectively (although performance will not be so great):
SELECT p.*, t.Technique as ParsedTechnique
FROM Personnel p join
Techniques t
on ','+p.technique+',' like '%,'+cast(t.id as varchar(255))+',%'
WHERE t.id = 1;
If performance is an issue, then fix your data structure an include a PersonTechniques
table so you can do a proper join.