Filter by using in for SQL Server












0















I have the below table



Col1       Col2
1 ACA,ABS,PHR
2 PHR
3 MCM
4 ABC


Now I want to filter the data from this so if I have a filter parameter as say 'ABS,MCM' I want to get only the rows which have at least one matching code. So in this case I should get the filtered result as



Col1       Col2
1 ACA,ABS,PHR
2 MCM


Now I can use the query Select * from myTable where Col2 in ('ABS','MCM') but then it won't retrieve the first row ACA,ABS,PHR. Can some one please tell me how I can do a text search for codes so as long as one code matches in Col2 I get the row so I can pass in directly the , delimited list and as long as it finds a single match the row is retrieved.



Thanks










share|improve this question



























    0















    I have the below table



    Col1       Col2
    1 ACA,ABS,PHR
    2 PHR
    3 MCM
    4 ABC


    Now I want to filter the data from this so if I have a filter parameter as say 'ABS,MCM' I want to get only the rows which have at least one matching code. So in this case I should get the filtered result as



    Col1       Col2
    1 ACA,ABS,PHR
    2 MCM


    Now I can use the query Select * from myTable where Col2 in ('ABS','MCM') but then it won't retrieve the first row ACA,ABS,PHR. Can some one please tell me how I can do a text search for codes so as long as one code matches in Col2 I get the row so I can pass in directly the , delimited list and as long as it finds a single match the row is retrieved.



    Thanks










    share|improve this question

























      0












      0








      0








      I have the below table



      Col1       Col2
      1 ACA,ABS,PHR
      2 PHR
      3 MCM
      4 ABC


      Now I want to filter the data from this so if I have a filter parameter as say 'ABS,MCM' I want to get only the rows which have at least one matching code. So in this case I should get the filtered result as



      Col1       Col2
      1 ACA,ABS,PHR
      2 MCM


      Now I can use the query Select * from myTable where Col2 in ('ABS','MCM') but then it won't retrieve the first row ACA,ABS,PHR. Can some one please tell me how I can do a text search for codes so as long as one code matches in Col2 I get the row so I can pass in directly the , delimited list and as long as it finds a single match the row is retrieved.



      Thanks










      share|improve this question














      I have the below table



      Col1       Col2
      1 ACA,ABS,PHR
      2 PHR
      3 MCM
      4 ABC


      Now I want to filter the data from this so if I have a filter parameter as say 'ABS,MCM' I want to get only the rows which have at least one matching code. So in this case I should get the filtered result as



      Col1       Col2
      1 ACA,ABS,PHR
      2 MCM


      Now I can use the query Select * from myTable where Col2 in ('ABS','MCM') but then it won't retrieve the first row ACA,ABS,PHR. Can some one please tell me how I can do a text search for codes so as long as one code matches in Col2 I get the row so I can pass in directly the , delimited list and as long as it finds a single match the row is retrieved.



      Thanks







      sql-server sql-server-2012






      share|improve this question













      share|improve this question











      share|improve this question




      share|improve this question










      asked Feb 14 at 19:05









      user1221989user1221989

      1444




      1444






















          5 Answers
          5






          active

          oldest

          votes


















          3














          You could also split the string and then search on the splitted values.
          An example could be by creating and using this function.



          Starting from SQL Server 2016 you could use the built in STRING_SPLIT() function.



          Creating the function from the blogpost and executing this query afterwards



          SELECT DISTINCT Col1,Col2 
          FROM dbo.Searching
          CROSS APPLY dbo.fnSplitString(col2,',')
          WHERE splitdata in ('ABS','MCM');


          Result



          Col1    Col2
          1 ACA,ABS,PHR
          3 MCM


          DB<>Fiddle



          An optimization could be proactively splitting the table into a permanent one so you don't need to do splitting on the entire table everytime. (If the values are static)





          EDIT



          Comment by @Erikdarling




          There are better ways to split strings: Comparing string splitting /
          concatenation methods, including a much better one at SSC by Jeff
          Moden.




          The function by Jeff Moden



          After creating the function in his blogpost, you could use a query that resembles the previous one.



            SELECT Col1,Col2
          FROM dbo.Searching
          CROSS APPLY dbo.DelimitedSplit8k(Col2,',') split
          WHERE split.Item in ('ABS','MCM');


          DB<>Fiddle






          share|improve this answer

































            3














            When I see filter parameter, I think input parameter to a stored procedure, so nothing hardcoded in the actual query. This is a twist on @Randi's version that uses an inline string splitter technique to split the incoming parameter into rows and using CROSS APPLY and LIKE to find matches.



            --demo setup
            declare @T table(col1 int, col2 varchar(100))
            insert into @T(col1,col2) values
            (1,'ACA,ABS,PHR'),
            (2,'PHR'),
            (3,'MCM'),
            (4,'ABC')

            --Declare the input parameter - passed into a stored procedure perhaps?
            Declare @Parm varchar(100) = 'ABS,MCM'


            --Common Table Expression - Inline string splitter, since you can't use STRING_SPLIT() from SQL 2016
            ;WITH SplitParms
            AS (
            SELECT LTRIM(RTRIM(m.n.value('.[1]', 'varchar(8000)'))) AS Code
            FROM (
            SELECT CAST('<XMLRoot><RowData>' + REPLACE(@Parm, ',', '</RowData><RowData>') + '</RowData></XMLRoot>' AS XML) AS x
            ) t
            CROSS APPLY x.nodes('/XMLRoot/RowData') m(n)
            )
            --use CROSS APPLY and LIKE to find matching rows
            SELECT t.*
            FROM @t t
            CROSS APPLY SplitParms sp
            WHERE t.col2 LIKE ('%' + sp.Code + '%')




            | col1 | col2        |
            |------|-------------|
            | 1 | ACA,ABS,PHR |
            | 3 | MCM |





            share|improve this answer































              1














              You would need to use like.
              where col2 like '%ABS%' or col2 like '%MCM%'






              share|improve this answer





















              • 1





                Agreed that this will work, but I cannot help but feel that there must be an easier/more dynamic way of doing this.

                – WadeH
                Feb 14 at 19:30











              • @WadeH It depends on the codes. It will fail if LABST is also a code.

                – jpmc26
                Feb 15 at 0:44



















              1














              Here is another solution. I don't have a large enough dataset to show performance gains either way, but one option (my Attempt 1) splits the string you are searching rather than the entire table. Of course, unbound string searches may be more costly than you want to pay, but you can do testing to show. Alternatively, in Attempt 3, I show how you can do it without using a string of OR clauses or string_split.



              /** BUILD UP DATA */
              DECLARE @SearchString VARCHAR(100) = 'ABS,MCM'

              DECLARE @Test TABLE
              (
              Col1 INT NOT NULL PRIMARY KEY IDENTITY(1,1)
              , Col2 VARCHAR(100) NULL
              )

              INSERT INTO @Test
              (Col2)
              VALUES ('ACA,ABS PHR')
              , ('PHR')
              , ('MCM')
              , ('ABC')
              , ('ABS,MCM') --Included to demonstrate if one record has multiple code matches.

              /** ATTEMPT 1 - UNBOUNDED WILDCARD SEARCH
              - Still uses STRING_SPLIT, just on the Search String rather than the main table.
              */
              ;WITH CTE_Distinct AS
              (
              SELECT T.*
              , RN = ROW_NUMBER() OVER (PARTITION BY T.Col1 ORDER BY T.Col1)
              FROM @Test AS T
              CROSS APPLY STRING_SPLIT(@SearchString, ',') AS V
              WHERE T.Col2 LIKE '%' + LTRIM(RTRIM(V.value)) + '%'
              )
              SELECT * FROM CTE_Distinct WHERE RN = 1

              /** ATTEMPT 2 - DIRECT QUERY,
              but uses STRING_SPLIT on the Col2
              */
              ;WITH CTE_Distinct AS
              (
              SELECT T.*
              , RN = ROW_NUMBER() OVER (PARTITION BY T.Col1 ORDER BY T.Col1)
              FROM @Test AS T
              CROSS APPLY STRING_SPLIT(T.Col2, ',') AS V
              WHERE V.value IN ('ABS', 'MCM')
              )
              SELECT * FROM CTE_Distinct WHERE RN = 1

              /** ATTEMPT 3 - UNBOUND WILDCARD, but no string splitting required.
              */
              DECLARE @SearchTable TABLE
              (
              Code VARCHAR(3) NOT NULL
              )

              INSERT INTO @SearchTable
              (Code)
              VALUES ('ABS')
              , ('MCM')

              ;WITH CTE_Distinct AS
              (
              SELECT T.*
              , RN = ROW_NUMBER() OVER (PARTITION BY T.Col1 ORDER BY T.Col1)
              FROM @Test AS T
              INNER JOIN @SearchTable AS P ON T.Col2 LIKE '%' + P.Code + '%'
              )
              SELECT * FROM CTE_Distinct WHERE RN = 1





              share|improve this answer































                1














                The most correct solution is to normalize. You need to put the codes in another table with a foreign key:



                CREATE TABLE MyThings (
                Col1 IDENTITY PRIMARY KEY,
                -- Other columns you already have on the table
                Col3 VARCHAR(200) NOT NULL,
                Col4 DECIMAL NOT NULL
                );

                -- Probably needs some kind of primary key.
                CREATE TABLE MyThingCodes (
                Col1 NOT NULL REFERENCES MyThings (Col1),
                Code VARCHAR(30) NOT NULL
                );


                And we can index it (since the codes are short) to speed up these queries:



                CREATE INDEX idx_MyThingCodes_Code ON MyThingCodes (Code);


                Then you can use an EXISTS query to find rows that match the code:



                SELECT *
                FROM MyThings
                WHERE EXISTS (
                SELECT 1
                FROM MyThingCodes
                WHERE
                MyThingCodes.Col1 = MyThings.Col1
                AND MyThingCodes.Code IN ('ABS','MCM')
                )





                share|improve this answer

























                  Your Answer








                  StackExchange.ready(function() {
                  var channelOptions = {
                  tags: "".split(" "),
                  id: "182"
                  };
                  initTagRenderer("".split(" "), "".split(" "), channelOptions);

                  StackExchange.using("externalEditor", function() {
                  // Have to fire editor after snippets, if snippets enabled
                  if (StackExchange.settings.snippets.snippetsEnabled) {
                  StackExchange.using("snippets", function() {
                  createEditor();
                  });
                  }
                  else {
                  createEditor();
                  }
                  });

                  function createEditor() {
                  StackExchange.prepareEditor({
                  heartbeatType: 'answer',
                  autoActivateHeartbeat: false,
                  convertImagesToLinks: false,
                  noModals: true,
                  showLowRepImageUploadWarning: true,
                  reputationToPostImages: null,
                  bindNavPrevention: true,
                  postfix: "",
                  imageUploader: {
                  brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
                  contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
                  allowUrls: true
                  },
                  onDemand: true,
                  discardSelector: ".discard-answer"
                  ,immediatelyShowMarkdownHelp:true
                  });


                  }
                  });














                  draft saved

                  draft discarded


















                  StackExchange.ready(
                  function () {
                  StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fdba.stackexchange.com%2fquestions%2f229784%2ffilter-by-using-in-for-sql-server%23new-answer', 'question_page');
                  }
                  );

                  Post as a guest















                  Required, but never shown

























                  5 Answers
                  5






                  active

                  oldest

                  votes








                  5 Answers
                  5






                  active

                  oldest

                  votes









                  active

                  oldest

                  votes






                  active

                  oldest

                  votes









                  3














                  You could also split the string and then search on the splitted values.
                  An example could be by creating and using this function.



                  Starting from SQL Server 2016 you could use the built in STRING_SPLIT() function.



                  Creating the function from the blogpost and executing this query afterwards



                  SELECT DISTINCT Col1,Col2 
                  FROM dbo.Searching
                  CROSS APPLY dbo.fnSplitString(col2,',')
                  WHERE splitdata in ('ABS','MCM');


                  Result



                  Col1    Col2
                  1 ACA,ABS,PHR
                  3 MCM


                  DB<>Fiddle



                  An optimization could be proactively splitting the table into a permanent one so you don't need to do splitting on the entire table everytime. (If the values are static)





                  EDIT



                  Comment by @Erikdarling




                  There are better ways to split strings: Comparing string splitting /
                  concatenation methods, including a much better one at SSC by Jeff
                  Moden.




                  The function by Jeff Moden



                  After creating the function in his blogpost, you could use a query that resembles the previous one.



                    SELECT Col1,Col2
                  FROM dbo.Searching
                  CROSS APPLY dbo.DelimitedSplit8k(Col2,',') split
                  WHERE split.Item in ('ABS','MCM');


                  DB<>Fiddle






                  share|improve this answer






























                    3














                    You could also split the string and then search on the splitted values.
                    An example could be by creating and using this function.



                    Starting from SQL Server 2016 you could use the built in STRING_SPLIT() function.



                    Creating the function from the blogpost and executing this query afterwards



                    SELECT DISTINCT Col1,Col2 
                    FROM dbo.Searching
                    CROSS APPLY dbo.fnSplitString(col2,',')
                    WHERE splitdata in ('ABS','MCM');


                    Result



                    Col1    Col2
                    1 ACA,ABS,PHR
                    3 MCM


                    DB<>Fiddle



                    An optimization could be proactively splitting the table into a permanent one so you don't need to do splitting on the entire table everytime. (If the values are static)





                    EDIT



                    Comment by @Erikdarling




                    There are better ways to split strings: Comparing string splitting /
                    concatenation methods, including a much better one at SSC by Jeff
                    Moden.




                    The function by Jeff Moden



                    After creating the function in his blogpost, you could use a query that resembles the previous one.



                      SELECT Col1,Col2
                    FROM dbo.Searching
                    CROSS APPLY dbo.DelimitedSplit8k(Col2,',') split
                    WHERE split.Item in ('ABS','MCM');


                    DB<>Fiddle






                    share|improve this answer




























                      3












                      3








                      3







                      You could also split the string and then search on the splitted values.
                      An example could be by creating and using this function.



                      Starting from SQL Server 2016 you could use the built in STRING_SPLIT() function.



                      Creating the function from the blogpost and executing this query afterwards



                      SELECT DISTINCT Col1,Col2 
                      FROM dbo.Searching
                      CROSS APPLY dbo.fnSplitString(col2,',')
                      WHERE splitdata in ('ABS','MCM');


                      Result



                      Col1    Col2
                      1 ACA,ABS,PHR
                      3 MCM


                      DB<>Fiddle



                      An optimization could be proactively splitting the table into a permanent one so you don't need to do splitting on the entire table everytime. (If the values are static)





                      EDIT



                      Comment by @Erikdarling




                      There are better ways to split strings: Comparing string splitting /
                      concatenation methods, including a much better one at SSC by Jeff
                      Moden.




                      The function by Jeff Moden



                      After creating the function in his blogpost, you could use a query that resembles the previous one.



                        SELECT Col1,Col2
                      FROM dbo.Searching
                      CROSS APPLY dbo.DelimitedSplit8k(Col2,',') split
                      WHERE split.Item in ('ABS','MCM');


                      DB<>Fiddle






                      share|improve this answer















                      You could also split the string and then search on the splitted values.
                      An example could be by creating and using this function.



                      Starting from SQL Server 2016 you could use the built in STRING_SPLIT() function.



                      Creating the function from the blogpost and executing this query afterwards



                      SELECT DISTINCT Col1,Col2 
                      FROM dbo.Searching
                      CROSS APPLY dbo.fnSplitString(col2,',')
                      WHERE splitdata in ('ABS','MCM');


                      Result



                      Col1    Col2
                      1 ACA,ABS,PHR
                      3 MCM


                      DB<>Fiddle



                      An optimization could be proactively splitting the table into a permanent one so you don't need to do splitting on the entire table everytime. (If the values are static)





                      EDIT



                      Comment by @Erikdarling




                      There are better ways to split strings: Comparing string splitting /
                      concatenation methods, including a much better one at SSC by Jeff
                      Moden.




                      The function by Jeff Moden



                      After creating the function in his blogpost, you could use a query that resembles the previous one.



                        SELECT Col1,Col2
                      FROM dbo.Searching
                      CROSS APPLY dbo.DelimitedSplit8k(Col2,',') split
                      WHERE split.Item in ('ABS','MCM');


                      DB<>Fiddle







                      share|improve this answer














                      share|improve this answer



                      share|improve this answer








                      edited Feb 14 at 20:18

























                      answered Feb 14 at 19:31









                      Randi VertongenRandi Vertongen

                      2,876721




                      2,876721

























                          3














                          When I see filter parameter, I think input parameter to a stored procedure, so nothing hardcoded in the actual query. This is a twist on @Randi's version that uses an inline string splitter technique to split the incoming parameter into rows and using CROSS APPLY and LIKE to find matches.



                          --demo setup
                          declare @T table(col1 int, col2 varchar(100))
                          insert into @T(col1,col2) values
                          (1,'ACA,ABS,PHR'),
                          (2,'PHR'),
                          (3,'MCM'),
                          (4,'ABC')

                          --Declare the input parameter - passed into a stored procedure perhaps?
                          Declare @Parm varchar(100) = 'ABS,MCM'


                          --Common Table Expression - Inline string splitter, since you can't use STRING_SPLIT() from SQL 2016
                          ;WITH SplitParms
                          AS (
                          SELECT LTRIM(RTRIM(m.n.value('.[1]', 'varchar(8000)'))) AS Code
                          FROM (
                          SELECT CAST('<XMLRoot><RowData>' + REPLACE(@Parm, ',', '</RowData><RowData>') + '</RowData></XMLRoot>' AS XML) AS x
                          ) t
                          CROSS APPLY x.nodes('/XMLRoot/RowData') m(n)
                          )
                          --use CROSS APPLY and LIKE to find matching rows
                          SELECT t.*
                          FROM @t t
                          CROSS APPLY SplitParms sp
                          WHERE t.col2 LIKE ('%' + sp.Code + '%')




                          | col1 | col2        |
                          |------|-------------|
                          | 1 | ACA,ABS,PHR |
                          | 3 | MCM |





                          share|improve this answer




























                            3














                            When I see filter parameter, I think input parameter to a stored procedure, so nothing hardcoded in the actual query. This is a twist on @Randi's version that uses an inline string splitter technique to split the incoming parameter into rows and using CROSS APPLY and LIKE to find matches.



                            --demo setup
                            declare @T table(col1 int, col2 varchar(100))
                            insert into @T(col1,col2) values
                            (1,'ACA,ABS,PHR'),
                            (2,'PHR'),
                            (3,'MCM'),
                            (4,'ABC')

                            --Declare the input parameter - passed into a stored procedure perhaps?
                            Declare @Parm varchar(100) = 'ABS,MCM'


                            --Common Table Expression - Inline string splitter, since you can't use STRING_SPLIT() from SQL 2016
                            ;WITH SplitParms
                            AS (
                            SELECT LTRIM(RTRIM(m.n.value('.[1]', 'varchar(8000)'))) AS Code
                            FROM (
                            SELECT CAST('<XMLRoot><RowData>' + REPLACE(@Parm, ',', '</RowData><RowData>') + '</RowData></XMLRoot>' AS XML) AS x
                            ) t
                            CROSS APPLY x.nodes('/XMLRoot/RowData') m(n)
                            )
                            --use CROSS APPLY and LIKE to find matching rows
                            SELECT t.*
                            FROM @t t
                            CROSS APPLY SplitParms sp
                            WHERE t.col2 LIKE ('%' + sp.Code + '%')




                            | col1 | col2        |
                            |------|-------------|
                            | 1 | ACA,ABS,PHR |
                            | 3 | MCM |





                            share|improve this answer


























                              3












                              3








                              3







                              When I see filter parameter, I think input parameter to a stored procedure, so nothing hardcoded in the actual query. This is a twist on @Randi's version that uses an inline string splitter technique to split the incoming parameter into rows and using CROSS APPLY and LIKE to find matches.



                              --demo setup
                              declare @T table(col1 int, col2 varchar(100))
                              insert into @T(col1,col2) values
                              (1,'ACA,ABS,PHR'),
                              (2,'PHR'),
                              (3,'MCM'),
                              (4,'ABC')

                              --Declare the input parameter - passed into a stored procedure perhaps?
                              Declare @Parm varchar(100) = 'ABS,MCM'


                              --Common Table Expression - Inline string splitter, since you can't use STRING_SPLIT() from SQL 2016
                              ;WITH SplitParms
                              AS (
                              SELECT LTRIM(RTRIM(m.n.value('.[1]', 'varchar(8000)'))) AS Code
                              FROM (
                              SELECT CAST('<XMLRoot><RowData>' + REPLACE(@Parm, ',', '</RowData><RowData>') + '</RowData></XMLRoot>' AS XML) AS x
                              ) t
                              CROSS APPLY x.nodes('/XMLRoot/RowData') m(n)
                              )
                              --use CROSS APPLY and LIKE to find matching rows
                              SELECT t.*
                              FROM @t t
                              CROSS APPLY SplitParms sp
                              WHERE t.col2 LIKE ('%' + sp.Code + '%')




                              | col1 | col2        |
                              |------|-------------|
                              | 1 | ACA,ABS,PHR |
                              | 3 | MCM |





                              share|improve this answer













                              When I see filter parameter, I think input parameter to a stored procedure, so nothing hardcoded in the actual query. This is a twist on @Randi's version that uses an inline string splitter technique to split the incoming parameter into rows and using CROSS APPLY and LIKE to find matches.



                              --demo setup
                              declare @T table(col1 int, col2 varchar(100))
                              insert into @T(col1,col2) values
                              (1,'ACA,ABS,PHR'),
                              (2,'PHR'),
                              (3,'MCM'),
                              (4,'ABC')

                              --Declare the input parameter - passed into a stored procedure perhaps?
                              Declare @Parm varchar(100) = 'ABS,MCM'


                              --Common Table Expression - Inline string splitter, since you can't use STRING_SPLIT() from SQL 2016
                              ;WITH SplitParms
                              AS (
                              SELECT LTRIM(RTRIM(m.n.value('.[1]', 'varchar(8000)'))) AS Code
                              FROM (
                              SELECT CAST('<XMLRoot><RowData>' + REPLACE(@Parm, ',', '</RowData><RowData>') + '</RowData></XMLRoot>' AS XML) AS x
                              ) t
                              CROSS APPLY x.nodes('/XMLRoot/RowData') m(n)
                              )
                              --use CROSS APPLY and LIKE to find matching rows
                              SELECT t.*
                              FROM @t t
                              CROSS APPLY SplitParms sp
                              WHERE t.col2 LIKE ('%' + sp.Code + '%')




                              | col1 | col2        |
                              |------|-------------|
                              | 1 | ACA,ABS,PHR |
                              | 3 | MCM |






                              share|improve this answer












                              share|improve this answer



                              share|improve this answer










                              answered Feb 14 at 20:04









                              Scott HodginScott Hodgin

                              17.4k21534




                              17.4k21534























                                  1














                                  You would need to use like.
                                  where col2 like '%ABS%' or col2 like '%MCM%'






                                  share|improve this answer





















                                  • 1





                                    Agreed that this will work, but I cannot help but feel that there must be an easier/more dynamic way of doing this.

                                    – WadeH
                                    Feb 14 at 19:30











                                  • @WadeH It depends on the codes. It will fail if LABST is also a code.

                                    – jpmc26
                                    Feb 15 at 0:44
















                                  1














                                  You would need to use like.
                                  where col2 like '%ABS%' or col2 like '%MCM%'






                                  share|improve this answer





















                                  • 1





                                    Agreed that this will work, but I cannot help but feel that there must be an easier/more dynamic way of doing this.

                                    – WadeH
                                    Feb 14 at 19:30











                                  • @WadeH It depends on the codes. It will fail if LABST is also a code.

                                    – jpmc26
                                    Feb 15 at 0:44














                                  1












                                  1








                                  1







                                  You would need to use like.
                                  where col2 like '%ABS%' or col2 like '%MCM%'






                                  share|improve this answer















                                  You would need to use like.
                                  where col2 like '%ABS%' or col2 like '%MCM%'







                                  share|improve this answer














                                  share|improve this answer



                                  share|improve this answer








                                  edited Feb 14 at 19:51









                                  Randi Vertongen

                                  2,876721




                                  2,876721










                                  answered Feb 14 at 19:13









                                  JoeDBA_HAHAHAJoeDBA_HAHAHA

                                  191




                                  191








                                  • 1





                                    Agreed that this will work, but I cannot help but feel that there must be an easier/more dynamic way of doing this.

                                    – WadeH
                                    Feb 14 at 19:30











                                  • @WadeH It depends on the codes. It will fail if LABST is also a code.

                                    – jpmc26
                                    Feb 15 at 0:44














                                  • 1





                                    Agreed that this will work, but I cannot help but feel that there must be an easier/more dynamic way of doing this.

                                    – WadeH
                                    Feb 14 at 19:30











                                  • @WadeH It depends on the codes. It will fail if LABST is also a code.

                                    – jpmc26
                                    Feb 15 at 0:44








                                  1




                                  1





                                  Agreed that this will work, but I cannot help but feel that there must be an easier/more dynamic way of doing this.

                                  – WadeH
                                  Feb 14 at 19:30





                                  Agreed that this will work, but I cannot help but feel that there must be an easier/more dynamic way of doing this.

                                  – WadeH
                                  Feb 14 at 19:30













                                  @WadeH It depends on the codes. It will fail if LABST is also a code.

                                  – jpmc26
                                  Feb 15 at 0:44





                                  @WadeH It depends on the codes. It will fail if LABST is also a code.

                                  – jpmc26
                                  Feb 15 at 0:44











                                  1














                                  Here is another solution. I don't have a large enough dataset to show performance gains either way, but one option (my Attempt 1) splits the string you are searching rather than the entire table. Of course, unbound string searches may be more costly than you want to pay, but you can do testing to show. Alternatively, in Attempt 3, I show how you can do it without using a string of OR clauses or string_split.



                                  /** BUILD UP DATA */
                                  DECLARE @SearchString VARCHAR(100) = 'ABS,MCM'

                                  DECLARE @Test TABLE
                                  (
                                  Col1 INT NOT NULL PRIMARY KEY IDENTITY(1,1)
                                  , Col2 VARCHAR(100) NULL
                                  )

                                  INSERT INTO @Test
                                  (Col2)
                                  VALUES ('ACA,ABS PHR')
                                  , ('PHR')
                                  , ('MCM')
                                  , ('ABC')
                                  , ('ABS,MCM') --Included to demonstrate if one record has multiple code matches.

                                  /** ATTEMPT 1 - UNBOUNDED WILDCARD SEARCH
                                  - Still uses STRING_SPLIT, just on the Search String rather than the main table.
                                  */
                                  ;WITH CTE_Distinct AS
                                  (
                                  SELECT T.*
                                  , RN = ROW_NUMBER() OVER (PARTITION BY T.Col1 ORDER BY T.Col1)
                                  FROM @Test AS T
                                  CROSS APPLY STRING_SPLIT(@SearchString, ',') AS V
                                  WHERE T.Col2 LIKE '%' + LTRIM(RTRIM(V.value)) + '%'
                                  )
                                  SELECT * FROM CTE_Distinct WHERE RN = 1

                                  /** ATTEMPT 2 - DIRECT QUERY,
                                  but uses STRING_SPLIT on the Col2
                                  */
                                  ;WITH CTE_Distinct AS
                                  (
                                  SELECT T.*
                                  , RN = ROW_NUMBER() OVER (PARTITION BY T.Col1 ORDER BY T.Col1)
                                  FROM @Test AS T
                                  CROSS APPLY STRING_SPLIT(T.Col2, ',') AS V
                                  WHERE V.value IN ('ABS', 'MCM')
                                  )
                                  SELECT * FROM CTE_Distinct WHERE RN = 1

                                  /** ATTEMPT 3 - UNBOUND WILDCARD, but no string splitting required.
                                  */
                                  DECLARE @SearchTable TABLE
                                  (
                                  Code VARCHAR(3) NOT NULL
                                  )

                                  INSERT INTO @SearchTable
                                  (Code)
                                  VALUES ('ABS')
                                  , ('MCM')

                                  ;WITH CTE_Distinct AS
                                  (
                                  SELECT T.*
                                  , RN = ROW_NUMBER() OVER (PARTITION BY T.Col1 ORDER BY T.Col1)
                                  FROM @Test AS T
                                  INNER JOIN @SearchTable AS P ON T.Col2 LIKE '%' + P.Code + '%'
                                  )
                                  SELECT * FROM CTE_Distinct WHERE RN = 1





                                  share|improve this answer




























                                    1














                                    Here is another solution. I don't have a large enough dataset to show performance gains either way, but one option (my Attempt 1) splits the string you are searching rather than the entire table. Of course, unbound string searches may be more costly than you want to pay, but you can do testing to show. Alternatively, in Attempt 3, I show how you can do it without using a string of OR clauses or string_split.



                                    /** BUILD UP DATA */
                                    DECLARE @SearchString VARCHAR(100) = 'ABS,MCM'

                                    DECLARE @Test TABLE
                                    (
                                    Col1 INT NOT NULL PRIMARY KEY IDENTITY(1,1)
                                    , Col2 VARCHAR(100) NULL
                                    )

                                    INSERT INTO @Test
                                    (Col2)
                                    VALUES ('ACA,ABS PHR')
                                    , ('PHR')
                                    , ('MCM')
                                    , ('ABC')
                                    , ('ABS,MCM') --Included to demonstrate if one record has multiple code matches.

                                    /** ATTEMPT 1 - UNBOUNDED WILDCARD SEARCH
                                    - Still uses STRING_SPLIT, just on the Search String rather than the main table.
                                    */
                                    ;WITH CTE_Distinct AS
                                    (
                                    SELECT T.*
                                    , RN = ROW_NUMBER() OVER (PARTITION BY T.Col1 ORDER BY T.Col1)
                                    FROM @Test AS T
                                    CROSS APPLY STRING_SPLIT(@SearchString, ',') AS V
                                    WHERE T.Col2 LIKE '%' + LTRIM(RTRIM(V.value)) + '%'
                                    )
                                    SELECT * FROM CTE_Distinct WHERE RN = 1

                                    /** ATTEMPT 2 - DIRECT QUERY,
                                    but uses STRING_SPLIT on the Col2
                                    */
                                    ;WITH CTE_Distinct AS
                                    (
                                    SELECT T.*
                                    , RN = ROW_NUMBER() OVER (PARTITION BY T.Col1 ORDER BY T.Col1)
                                    FROM @Test AS T
                                    CROSS APPLY STRING_SPLIT(T.Col2, ',') AS V
                                    WHERE V.value IN ('ABS', 'MCM')
                                    )
                                    SELECT * FROM CTE_Distinct WHERE RN = 1

                                    /** ATTEMPT 3 - UNBOUND WILDCARD, but no string splitting required.
                                    */
                                    DECLARE @SearchTable TABLE
                                    (
                                    Code VARCHAR(3) NOT NULL
                                    )

                                    INSERT INTO @SearchTable
                                    (Code)
                                    VALUES ('ABS')
                                    , ('MCM')

                                    ;WITH CTE_Distinct AS
                                    (
                                    SELECT T.*
                                    , RN = ROW_NUMBER() OVER (PARTITION BY T.Col1 ORDER BY T.Col1)
                                    FROM @Test AS T
                                    INNER JOIN @SearchTable AS P ON T.Col2 LIKE '%' + P.Code + '%'
                                    )
                                    SELECT * FROM CTE_Distinct WHERE RN = 1





                                    share|improve this answer


























                                      1












                                      1








                                      1







                                      Here is another solution. I don't have a large enough dataset to show performance gains either way, but one option (my Attempt 1) splits the string you are searching rather than the entire table. Of course, unbound string searches may be more costly than you want to pay, but you can do testing to show. Alternatively, in Attempt 3, I show how you can do it without using a string of OR clauses or string_split.



                                      /** BUILD UP DATA */
                                      DECLARE @SearchString VARCHAR(100) = 'ABS,MCM'

                                      DECLARE @Test TABLE
                                      (
                                      Col1 INT NOT NULL PRIMARY KEY IDENTITY(1,1)
                                      , Col2 VARCHAR(100) NULL
                                      )

                                      INSERT INTO @Test
                                      (Col2)
                                      VALUES ('ACA,ABS PHR')
                                      , ('PHR')
                                      , ('MCM')
                                      , ('ABC')
                                      , ('ABS,MCM') --Included to demonstrate if one record has multiple code matches.

                                      /** ATTEMPT 1 - UNBOUNDED WILDCARD SEARCH
                                      - Still uses STRING_SPLIT, just on the Search String rather than the main table.
                                      */
                                      ;WITH CTE_Distinct AS
                                      (
                                      SELECT T.*
                                      , RN = ROW_NUMBER() OVER (PARTITION BY T.Col1 ORDER BY T.Col1)
                                      FROM @Test AS T
                                      CROSS APPLY STRING_SPLIT(@SearchString, ',') AS V
                                      WHERE T.Col2 LIKE '%' + LTRIM(RTRIM(V.value)) + '%'
                                      )
                                      SELECT * FROM CTE_Distinct WHERE RN = 1

                                      /** ATTEMPT 2 - DIRECT QUERY,
                                      but uses STRING_SPLIT on the Col2
                                      */
                                      ;WITH CTE_Distinct AS
                                      (
                                      SELECT T.*
                                      , RN = ROW_NUMBER() OVER (PARTITION BY T.Col1 ORDER BY T.Col1)
                                      FROM @Test AS T
                                      CROSS APPLY STRING_SPLIT(T.Col2, ',') AS V
                                      WHERE V.value IN ('ABS', 'MCM')
                                      )
                                      SELECT * FROM CTE_Distinct WHERE RN = 1

                                      /** ATTEMPT 3 - UNBOUND WILDCARD, but no string splitting required.
                                      */
                                      DECLARE @SearchTable TABLE
                                      (
                                      Code VARCHAR(3) NOT NULL
                                      )

                                      INSERT INTO @SearchTable
                                      (Code)
                                      VALUES ('ABS')
                                      , ('MCM')

                                      ;WITH CTE_Distinct AS
                                      (
                                      SELECT T.*
                                      , RN = ROW_NUMBER() OVER (PARTITION BY T.Col1 ORDER BY T.Col1)
                                      FROM @Test AS T
                                      INNER JOIN @SearchTable AS P ON T.Col2 LIKE '%' + P.Code + '%'
                                      )
                                      SELECT * FROM CTE_Distinct WHERE RN = 1





                                      share|improve this answer













                                      Here is another solution. I don't have a large enough dataset to show performance gains either way, but one option (my Attempt 1) splits the string you are searching rather than the entire table. Of course, unbound string searches may be more costly than you want to pay, but you can do testing to show. Alternatively, in Attempt 3, I show how you can do it without using a string of OR clauses or string_split.



                                      /** BUILD UP DATA */
                                      DECLARE @SearchString VARCHAR(100) = 'ABS,MCM'

                                      DECLARE @Test TABLE
                                      (
                                      Col1 INT NOT NULL PRIMARY KEY IDENTITY(1,1)
                                      , Col2 VARCHAR(100) NULL
                                      )

                                      INSERT INTO @Test
                                      (Col2)
                                      VALUES ('ACA,ABS PHR')
                                      , ('PHR')
                                      , ('MCM')
                                      , ('ABC')
                                      , ('ABS,MCM') --Included to demonstrate if one record has multiple code matches.

                                      /** ATTEMPT 1 - UNBOUNDED WILDCARD SEARCH
                                      - Still uses STRING_SPLIT, just on the Search String rather than the main table.
                                      */
                                      ;WITH CTE_Distinct AS
                                      (
                                      SELECT T.*
                                      , RN = ROW_NUMBER() OVER (PARTITION BY T.Col1 ORDER BY T.Col1)
                                      FROM @Test AS T
                                      CROSS APPLY STRING_SPLIT(@SearchString, ',') AS V
                                      WHERE T.Col2 LIKE '%' + LTRIM(RTRIM(V.value)) + '%'
                                      )
                                      SELECT * FROM CTE_Distinct WHERE RN = 1

                                      /** ATTEMPT 2 - DIRECT QUERY,
                                      but uses STRING_SPLIT on the Col2
                                      */
                                      ;WITH CTE_Distinct AS
                                      (
                                      SELECT T.*
                                      , RN = ROW_NUMBER() OVER (PARTITION BY T.Col1 ORDER BY T.Col1)
                                      FROM @Test AS T
                                      CROSS APPLY STRING_SPLIT(T.Col2, ',') AS V
                                      WHERE V.value IN ('ABS', 'MCM')
                                      )
                                      SELECT * FROM CTE_Distinct WHERE RN = 1

                                      /** ATTEMPT 3 - UNBOUND WILDCARD, but no string splitting required.
                                      */
                                      DECLARE @SearchTable TABLE
                                      (
                                      Code VARCHAR(3) NOT NULL
                                      )

                                      INSERT INTO @SearchTable
                                      (Code)
                                      VALUES ('ABS')
                                      , ('MCM')

                                      ;WITH CTE_Distinct AS
                                      (
                                      SELECT T.*
                                      , RN = ROW_NUMBER() OVER (PARTITION BY T.Col1 ORDER BY T.Col1)
                                      FROM @Test AS T
                                      INNER JOIN @SearchTable AS P ON T.Col2 LIKE '%' + P.Code + '%'
                                      )
                                      SELECT * FROM CTE_Distinct WHERE RN = 1






                                      share|improve this answer












                                      share|improve this answer



                                      share|improve this answer










                                      answered Feb 14 at 20:18









                                      Jonathan FiteJonathan Fite

                                      4,058818




                                      4,058818























                                          1














                                          The most correct solution is to normalize. You need to put the codes in another table with a foreign key:



                                          CREATE TABLE MyThings (
                                          Col1 IDENTITY PRIMARY KEY,
                                          -- Other columns you already have on the table
                                          Col3 VARCHAR(200) NOT NULL,
                                          Col4 DECIMAL NOT NULL
                                          );

                                          -- Probably needs some kind of primary key.
                                          CREATE TABLE MyThingCodes (
                                          Col1 NOT NULL REFERENCES MyThings (Col1),
                                          Code VARCHAR(30) NOT NULL
                                          );


                                          And we can index it (since the codes are short) to speed up these queries:



                                          CREATE INDEX idx_MyThingCodes_Code ON MyThingCodes (Code);


                                          Then you can use an EXISTS query to find rows that match the code:



                                          SELECT *
                                          FROM MyThings
                                          WHERE EXISTS (
                                          SELECT 1
                                          FROM MyThingCodes
                                          WHERE
                                          MyThingCodes.Col1 = MyThings.Col1
                                          AND MyThingCodes.Code IN ('ABS','MCM')
                                          )





                                          share|improve this answer






























                                            1














                                            The most correct solution is to normalize. You need to put the codes in another table with a foreign key:



                                            CREATE TABLE MyThings (
                                            Col1 IDENTITY PRIMARY KEY,
                                            -- Other columns you already have on the table
                                            Col3 VARCHAR(200) NOT NULL,
                                            Col4 DECIMAL NOT NULL
                                            );

                                            -- Probably needs some kind of primary key.
                                            CREATE TABLE MyThingCodes (
                                            Col1 NOT NULL REFERENCES MyThings (Col1),
                                            Code VARCHAR(30) NOT NULL
                                            );


                                            And we can index it (since the codes are short) to speed up these queries:



                                            CREATE INDEX idx_MyThingCodes_Code ON MyThingCodes (Code);


                                            Then you can use an EXISTS query to find rows that match the code:



                                            SELECT *
                                            FROM MyThings
                                            WHERE EXISTS (
                                            SELECT 1
                                            FROM MyThingCodes
                                            WHERE
                                            MyThingCodes.Col1 = MyThings.Col1
                                            AND MyThingCodes.Code IN ('ABS','MCM')
                                            )





                                            share|improve this answer




























                                              1












                                              1








                                              1







                                              The most correct solution is to normalize. You need to put the codes in another table with a foreign key:



                                              CREATE TABLE MyThings (
                                              Col1 IDENTITY PRIMARY KEY,
                                              -- Other columns you already have on the table
                                              Col3 VARCHAR(200) NOT NULL,
                                              Col4 DECIMAL NOT NULL
                                              );

                                              -- Probably needs some kind of primary key.
                                              CREATE TABLE MyThingCodes (
                                              Col1 NOT NULL REFERENCES MyThings (Col1),
                                              Code VARCHAR(30) NOT NULL
                                              );


                                              And we can index it (since the codes are short) to speed up these queries:



                                              CREATE INDEX idx_MyThingCodes_Code ON MyThingCodes (Code);


                                              Then you can use an EXISTS query to find rows that match the code:



                                              SELECT *
                                              FROM MyThings
                                              WHERE EXISTS (
                                              SELECT 1
                                              FROM MyThingCodes
                                              WHERE
                                              MyThingCodes.Col1 = MyThings.Col1
                                              AND MyThingCodes.Code IN ('ABS','MCM')
                                              )





                                              share|improve this answer















                                              The most correct solution is to normalize. You need to put the codes in another table with a foreign key:



                                              CREATE TABLE MyThings (
                                              Col1 IDENTITY PRIMARY KEY,
                                              -- Other columns you already have on the table
                                              Col3 VARCHAR(200) NOT NULL,
                                              Col4 DECIMAL NOT NULL
                                              );

                                              -- Probably needs some kind of primary key.
                                              CREATE TABLE MyThingCodes (
                                              Col1 NOT NULL REFERENCES MyThings (Col1),
                                              Code VARCHAR(30) NOT NULL
                                              );


                                              And we can index it (since the codes are short) to speed up these queries:



                                              CREATE INDEX idx_MyThingCodes_Code ON MyThingCodes (Code);


                                              Then you can use an EXISTS query to find rows that match the code:



                                              SELECT *
                                              FROM MyThings
                                              WHERE EXISTS (
                                              SELECT 1
                                              FROM MyThingCodes
                                              WHERE
                                              MyThingCodes.Col1 = MyThings.Col1
                                              AND MyThingCodes.Code IN ('ABS','MCM')
                                              )






                                              share|improve this answer














                                              share|improve this answer



                                              share|improve this answer








                                              edited Feb 15 at 2:24

























                                              answered Feb 15 at 0:54









                                              jpmc26jpmc26

                                              8111126




                                              8111126






























                                                  draft saved

                                                  draft discarded




















































                                                  Thanks for contributing an answer to Database Administrators Stack Exchange!


                                                  • Please be sure to answer the question. Provide details and share your research!

                                                  But avoid



                                                  • Asking for help, clarification, or responding to other answers.

                                                  • Making statements based on opinion; back them up with references or personal experience.


                                                  To learn more, see our tips on writing great answers.




                                                  draft saved


                                                  draft discarded














                                                  StackExchange.ready(
                                                  function () {
                                                  StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fdba.stackexchange.com%2fquestions%2f229784%2ffilter-by-using-in-for-sql-server%23new-answer', 'question_page');
                                                  }
                                                  );

                                                  Post as a guest















                                                  Required, but never shown





















































                                                  Required, but never shown














                                                  Required, but never shown












                                                  Required, but never shown







                                                  Required, but never shown

































                                                  Required, but never shown














                                                  Required, but never shown












                                                  Required, but never shown







                                                  Required, but never shown







                                                  Popular posts from this blog

                                                  Biblatex bibliography style without URLs when DOI exists (in Overleaf with Zotero bibliography)

                                                  ComboBox Display Member on multiple fields

                                                  Is it possible to collect Nectar points via Trainline?