Dynamic filtering of stored procedure with IN parameter

  • Hi All, I want to dynamically filter a stored procedure with 2 parameters that contain a delimited list of values that can be fed into the IN clause of a stored procedure.

    SELECT Answer

    FROM dbo.TBL_ComplianceAnswers

    WHERE (QueID IN (371, 373, 404)) AND (ServiceID IN (120, 65))

    The stored procedure works fine with fixed values but I'd like the filtering values to be dynamically changed and to pass a delimited list of QueID values '371, 373, 404' and ServiceID values '120, 65' and for them to become parameters within the stored procedure suh as the following.

    SELECT Answer

    FROM dbo.TBL_ComplianceAnswers

    WHERE (QueID IN (@QueID)) AND (ServiceID IN (@ServID))

    Is this possible? does anyone have a bit of TSQL sample code I could play with.

    Thanks,

    Joe

  • Start here.

    http://www.sqlservercentral.com/articles/Tally+Table/72993/

    Michael L John
    If you assassinate a DBA, would you pull a trigger?
    To properly post on a forum:
    http://www.sqlservercentral.com/articles/61537/

  • Hi Michael, thank you for for the quick reply, I've had a look at the sample and created the function, but I can't see how to apply it to my situation.

    Let's say I have a simple table with a list of 50 cities and I want to filter out London, New York, Paris how would I use that splitter in that situation, bearing in mind that I want to pass 'London', 'New York', 'Baltimore', 'Paris' as a single parameter.

    SELECT City, Country, Population

    FROM tblCities

    WHERE (City IN ('London', 'New York', 'Baltimore', 'Paris'))

    I'm new to TSQL so thanks for your patience.

    Thanks

  • SELECT City, Country, Population

    FROM tblCities

    WHERE EXISTS (SELECT SP.item FROM dbo.DelimitedSplit8k('London,paris,new york',',') SP WHERE SP.item = tblCities.City)

    OR

    SELECT CTY.City, CTY.Country, CTY.Population

    FROM tblCities CTY

    INNER JOIN dbo.DelimitedSplit8k('London,paris,new york',',') SP ON CTY.City = SP.Item

    The function DelimitedSplit8k is a table valued function. It returns a table so treat it like a table. Do a join, or an "if exists".

    Are you a student? Because this kind of naming ("tblCities") will get you laughed at where I work.

    What is the point of a three character prefix?

    As a beginner, spend a day or two reading this series of articles.

    http://www.sqlservercentral.com/stairway/

    Then, post whatever questions you may have to the discussion forums.

    Michael L John
    If you assassinate a DBA, would you pull a trigger?
    To properly post on a forum:
    http://www.sqlservercentral.com/articles/61537/

  • Michael, thank you so much for your patience and quick reply, greatly appreciated. I've now got it working with your help!!

    I'm an Access developer looking to upsize to SQL Server. In the Access world of coding, prefixing of objects is known as the Leszynski naming convention it's a habit I'll have to break by the look of it. ๐Ÿ™‚ I'll follow through on your suggestion to read through those articles.

    Cheers,

  • Accept the two parameters as comma separated string.

    Create a function that will split the comma separated string and returns table.

    And use that function in where clause

  • Bhushan Kulkarni (1/21/2015)


    Accept the two parameters as comma separated string.

    Create a function that will split the comma separated string and returns table.

    And use that function in where clause

    More or less what Michael L John recommends, except Michael links to an article which covers a string-splitter in some detail. Can you create a better one? Also, you suggest using the splitter function in the WHERE clause. Can you show how you might do this, and what benefits it might provide over the two complete solutions proposed by Michael?

    โ€œWrite the query the simplest way. If through testing it becomes clear that the performance is inadequate, consider alternative query forms.โ€ - Gail Shaw

    For fast, accurate and documented assistance in answering your questions, please read this article.
    Understanding and using APPLY, (I) and (II) Paul White
    Hidden RBAR: Triangular Joins / The "Numbers" or "Tally" Table: What it is and how it replaces a loop Jeff Moden

  • There is no better splitter function!

    Michael L John
    If you assassinate a DBA, would you pull a trigger?
    To properly post on a forum:
    http://www.sqlservercentral.com/articles/61537/

  • I did come across this one on the stackoverflow website, I can't vouch for it's efficiency but it works just fine.

    CREATE FUNCTION [dbo].[ufn_CSVToTable] ( @StringInput VARCHAR(8000), @Delimiter nvarchar(1))

    RETURNS @OutputTable TABLE ( [String] VARCHAR(10) )

    AS

    BEGIN

    DECLARE @String VARCHAR(10)

    WHILE LEN(@StringInput) > 0

    BEGIN

    SET @String = LEFT(@StringInput,

    ISNULL(NULLIF(CHARINDEX(@Delimiter, @StringInput) - 1, -1),

    LEN(@StringInput)))

    SET @StringInput = SUBSTRING(@StringInput,

    ISNULL(NULLIF(CHARINDEX(@Delimiter, @StringInput), 0),

    LEN(@StringInput)) + 1, LEN(@StringInput))

    INSERT INTO @OutputTable ( [String] )

    VALUES ( @String )

    END

    RETURN

    END

    GO

    This is an example of its use...

    declare @table table

    (

    rownum int,

    csv nvarchar(300)

    )

    insert into @table values (1,'VALUE1, VALUE2, VALUE3')

    insert into @table values (2,'VALUE1, VALUE2')

    insert into @table values (3,'VALUE1, VALUE3')

    insert into @table values (4,'VALUE2, VALUE3')

    insert into @table values (5,'VALUE1, VALUE2, VALUE3')

    insert into @table values (6,'VALUE3, VALUE1, VALUE2')

    insert into @table values (7,'VALUE2, VALUE1')

    declare @Filter nvarchar(50)

    set @Filter = 'VALUE3,VALUE4'

    select * from @table

    SELECT * INTO #FilterTable FROM ufn_CSVToTable(@Filter, ',')

    SELECT * FROM #FilterTable

    select * from @table where EXISTS(SELECT String FROM #FilterTable WHERE csv like '%' + String + '%')

    DROP TABLE #FilterTable

  • There are numerous splitter functions out there.

    The example you provided uses a loop.

    If you read the article, the performance of a loop splitter is significantly worse than Jeff Moden's splitter when the strings get longer.

    For only a few elements, the performance is likely the same.

    Michael L John
    If you assassinate a DBA, would you pull a trigger?
    To properly post on a forum:
    http://www.sqlservercentral.com/articles/61537/

  • SELECT *

    FROM @table t

    WHERE EXISTS (SELECT 1 FROM ufn_CSVToTable(@Filter, ',') s WHERE t.csv LIKE '%'+s.String+'%')

    SELECT *

    FROM @table t

    WHERE EXISTS (

    SELECT 1 FROM ufn_CSVToTable(@Filter, ',') s1

    INNER JOIN ufn_CSVToTable(t.csv, ',') s2

    ON LTRIM(s2.String) = s1.String)

    -- splitter ufn_CSVToTable leaves leading space:

    SELECT '['+string+']' FROM ufn_CSVToTable('VALUE3, VALUE1, VALUE2', ',')

    โ€œWrite the query the simplest way. If through testing it becomes clear that the performance is inadequate, consider alternative query forms.โ€ - Gail Shaw

    For fast, accurate and documented assistance in answering your questions, please read this article.
    Understanding and using APPLY, (I) and (II) Paul White
    Hidden RBAR: Triangular Joins / The "Numbers" or "Tally" Table: What it is and how it replaces a loop Jeff Moden

  • Michael is right - there are probably almost as many string splitter functions as there are questions about them. Some of them work better than others, but Jeff's DelimitedSplit8K is certainly the fastest one I've found that works on SQL 2005+. The first two links in my signature go to the Tally table article and the Tally Oh article, where the DelimitedSplit8K is explained and compared with other approaches to the very common problem of splitting strings.

    But, don't take Michael's, mine or anyone else's word for it. Test it out yourself. I'd run it over a 1 million row table to start. You might not need to run it over something that big today, but you might in the future. In performance testing, you want to find and fix weakness. Running a test of 100 rows should work great, but 1M rows will probably expose weakness. Who knows? You might even find ways to improve it. ๐Ÿ˜‰

Viewing 12 posts - 1 through 11 (of 11 total)

You must be logged in to reply to this topic. Login to reply