Question

I have a Table Valued Parameter (@KEYWORD) which just has one column with 0 to many rows of keywords that will query against one or two database (nvarchar) columns (REMARKS and SUPPLEMENTAL_REMARKS). Super simple concept.

What I am having trouble with is how to write the SQL to have it check for each of the individual keywords supplied against that one (or two) database columns.

Here's my unfinished part of the WHERE clause...

WHERE
(
    CASE WHEN EXISTS (SELECT 1 FROM @KEYWORD) THEN
        --check that some combination of either REMARKS or SUPPLEMENTAL_REMARKS contains all supplied values
        CASE WHEN (
        --  RES.REMARKS (or RES.SUPPLEMENTAL_REMARKS) LIKE %keyword[0]%
        --  AND
        --  RES.REMARKS (or RES.SUPPLEMENTAL_REMARKS) LIKE %keyword[1]%
        --  AND
        --  ... (this doesn't work for many reasons, but is just to give an idea)
        ) THEN
            1
        ELSE
            0
        END
    ELSE --TVP (@KEYWORD) not supplied, so ignore this filter
        1
    END
) = 1
Was it helpful?

Solution

Base on the SQL comment below you only want records from res where all the keyword match on either REMARKS or SUPPLEMENTAL_REMARKS.

 --  REMARKS (or SUPPLEMENTAL_REMARKS) LIKE %keyword[0]%
        --  AND
        --  REMARKS (or SUPPLEMENTAL_REMARKS) LIKE %keyword[1]%
        --  AND
        --  ... (this doesn't work for many reasons, but is just to give an idea)

The easiest way to do that is JOIN and do a count and make sure it matches the number of keywords in @KEYWORD

DECLARE @KEYWORDCOUNT as INT
SELECT @KEYWORDCOUNT = COUNT(*) FROM @Keyword

SELECT ID, [REMARKS], [SUPPLEMENTAL_REMARKS]
FROM 
  res r
  INNER JOIN @Keyword k
  ON r.REMARKS like '%' + k.keyword + '%'
     OR r.SUPPLEMENTAL_REMARKS like '%' + k.keyword + '%'


GROUP BY 
  ID,[REMARKS], [SUPPLEMENTAL_REMARKS]
HAVING COUNT(ID) = @KEYWORDCOUNT

One way for it into your where is like so

WHERE
  @KEYWORDCOUNT = 0 
  OR 
  res.id in (SELECT ID
            FROM 
                res r
                INNER JOIN @Keyword k
               ON r.REMARKS like '%' + k.keyword + '%'
                 OR r.SUPPLEMENTAL_REMARKS like '%' + k.keyword + '%'
             GROUP BY 
              ID
             HAVING COUNT(ID) = @KEYWORDCOUNT)

You might want to consider passing @KEYWORDCOUNT in as a parameter since DataTable.Rows.Count almost free

DEMO

OTHER TIPS

Can you use a JOIN? Then DISTINCT back to just the source table, so you don't get multiple rows of it when you match on multiple keywords.

select distinct res.*
from sourcetable res 
join @keywords kw on res.REMARKS like '%'+kw.keyword+'%' or res.SUPPLEMENTAL_REMARKS like '%'+kw.keyword+'%'

If you need all to match and just show all source rows when keywords empty

select res.id, res.REMARKS, res.SUPPLEMENTAL_REMARKS from (
  select res.id, res.REMARKS, res.SUPPLEMENTAL_REMARKS
  from sourcetable res
  join @keywords kw on res.REMARKS like '%'+kw.keyword+'%' or res.SUPPLEMENTAL_REMARKS like '%'+kw.keyword+'%'
  group by res.id, res.REMARKS, res.SUPPLEMENTAL_REMARKS
  having count(*) = (select count(*) from @keywords)
) k1 UNION ALL SELECT res.id, res.REMARKS, res.SUPPLEMENTAL_REMARKS FROM (
  SELECT * WHERE 0=(select count(*) from @keywords)
) k0
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top