The answer is to normalize your database.
In the meantime, a workaround that will perform better on large sets, is to use a temp table. (LIKE
searches can't use an index)
This approach also shows some steps towards normalizing the data and handles whitespace.
First create a "Tally Table" if you don't have one. This is a one-time deal, and Tally tables come in handy for all kinds of things.
/*--- Create a Tally table. This only needs to be done once.
Note that "Master.dbo.SysColumns" is in all SQL 2000 installations.
For SQL 2005, or later, use "master.sys.all_columns".
*/
SELECT TOP 11000 -- Adequate for most business purposes.
IDENTITY (INT, 1, 1) AS N
INTO
dbo.Tally
FROM
Master.dbo.SysColumns sc1,
Master.dbo.SysColumns sc2
--- Add a Primary Key to maximize performance.
ALTER TABLE dbo.Tally
ADD CONSTRAINT PK_Tally_N PRIMARY KEY CLUSTERED (N) WITH FILLFACTOR = 100
Now suppose your tables are:
CREATE TABLE ListO_Codes (ID INT IDENTITY(1,1), Code VARCHAR(88))
INSERT INTO ListO_Codes (Code)
SELECT '123,456,789,12' UNION ALL
SELECT '456,073' UNION ALL
SELECT '69,76,56'
CREATE TABLE AnotherTable (ID INT IDENTITY(1,1), Ref VARCHAR(8), CodeWord VARCHAR (88))
INSERT INTO AnotherTable (Ref, CodeWord)
SELECT '12', 'Children' UNION ALL
SELECT '123', 'of' UNION ALL
SELECT '456', '-' UNION ALL
SELECT '789', 'sun,' UNION ALL
SELECT '073', 'see' UNION ALL
SELECT '56', 'your' UNION ALL
SELECT '69', 'time' UNION ALL
SELECT '76', 'has'
Then the temp table is:
CREATE TABLE #NORMALIZED_Data (LOD_id INT, Ref int) -- Make Ref varchar if it's not numeric
INSERT INTO
#NORMALIZED_Data (LOD_id, Ref)
SELECT
L.ID,
-- Split Code string using Tally table and Delimiters
LTrim (RTrim (SUBSTRING (',' + L.Code + ',', T.N+1, CHARINDEX (',', ',' + L.Code + ',', T.N+1) - T.N - 1 ) ) )
FROM
dbo.Tally T,
ListO_Codes L
WHERE
T.N < LEN (',' + L.Code + ',')
AND
SUBSTRING (',' + L.Code + ',', T.N, 1) = ','
--- Index for performance
CREATE CLUSTERED INDEX CL_NORMALIZED_Data_LOD_id_Ref
ON #NORMALIZED_Data (LOD_id, Ref) WITH FILLFACTOR = 100
Then the search is:
SELECT
L.ID,
L.Code,
A.Ref,
A.CodeWord
FROM
#NORMALIZED_Data N
INNER JOIN
ListO_Codes L ON N.LOD_id = L.ID
LEFT JOIN
AnotherTable A ON N.Ref = A.Ref
ORDER BY
L.ID,
A.Ref
And the results are:
ID Code Ref CodeWord
-- -------------- --- --------
1 123,456,789,12 12 Children
1 123,456,789,12 123 of
1 123,456,789,12 456 -
1 123,456,789,12 789 sun,
2 456,073 073 see
2 456,073 456 -
3 69,76,56 56 your
3 69,76,56 69 time
3 69,76,56 76 has