2

I have a table called MyProducts and I want to return item1 and item2

SELECT item1, item2 from MyProducts

However I want it to be filtered on a string array I pass in (from C#). This is a very big table, so I an 'IN' statement is out. How would I do this using a join statement. Thanks!

3
  • 1
    Which version of sql-server? If you are on 2008 or more recent you can use table-valued-parameters Commented Oct 5, 2012 at 12:58
  • Is the column you're filtering indexed in any way (if so, what kind of index)? Pending the index/type, different searching options are available. Commented Oct 5, 2012 at 12:59
  • The columns I am filtering on are not indexed, they are just varchars that are the customer name. And yes, it is Sql server 2008 Commented Oct 5, 2012 at 13:00

3 Answers 3

2

There's no reason that IN statement is "out"; ultimately, that is a perfectly reasonable way of filtering - let the optimizer worry about the various options. It certainly isn't impacted by the fact that MyProducts is large. Adding a join makes more work: it does not, however, reduce the number of "hits", or the work involved. For example, to do that with dapper is just:

string[] filter = ...
var rows = connection.Query(
     "select item1, item2 from MyProducts where SomeField in @filter",
     new {filter});

or with LINQ:

string[] filter = ...
var rows = db.Products.Where(x => filter.Contains(x.SomeField));
Sign up to request clarification or add additional context in comments.

2 Comments

The OP didn't mention if the size of MyProducts or the filter array was the problem. If the filter array has more than 2000 items (approx.) SQL Will start to choke. Otherwise, Contains is a good solution for most cases.
@Jim if they need to get 2000 filter options down to the server for a single select, then there's already a problem - simply the bandwidth will make it sucky; sounds like a design issue if that is the case
1

One solution is to create a temporary table and join with it. The temporary table can have an index on the column on which you will be joining.

1 Comment

how would I do that? Not exactly sure how to handle an array
1

I always liked this method...

CREATE FUNCTION dbo.Split(@String varchar(max), @Delimiter char(1))        
returns @temptable TABLE (Value varchar(max))        
as        
begin        
    declare @idx int        
    declare @slice varchar(max)        

        select @idx = 1        
        if len(@String)<1 or @String is null  return        

    while @idx!= 0        
    begin        
        set @idx = charindex(@Delimiter,@String)        
        if @idx!=0        
            set @slice = left(@String,@idx - 1)        
        else        
            set @slice = @String        

        if(len(@slice)>0)   
            insert into @temptable(Items) values(@slice)        

        set @String = right(@String,len(@String) - @idx)        
        if len(@String) = 0 break        
    end    
return        
end 

then you can do this...

CREATE PROCEDURE MySp
    @list varchar(max)
AS 

SELECT <columns> 
  FROM <mytable> mt
 INNER JOIN dbo.split(@list,',') s ON s.Value= my.Key

NOTE: There are many Split functions out there so you do not have to use this specific one.


Another method I have used when using SQL Server 2008 is using a table parameter like this...

CREATE TYPE [dbo].[LookupTable] As Table
(
    ID Int primary key
)

CREATE PROCEDURE [dbo].[SampleProcedure]
(
    @idTable As [dbo].[LookupTable] Readonly
)
AS
BEGIN
    SELECT <columns> 
      FROM <mytable> mt
     INNER JOIN @idTable s ON s.Id= my.Key
END

Pass the parameter into SQL Server from C# in this manner...

DataTable dataTable = new DataTable("SampleDataType"); 
dataTable.Columns.Add("Id", typeof(Int32)); 
foreach (var id in <mycollectionofids>)
    dataTable.Rows.Add(id); 

SqlParameter parameter = new SqlParameter(); 
parameter.ParameterName="@Id"; 
parameter.SqlDbType = System.Data.SqlDbType.Structured; 
parameter.Value = dataTable; 
command.Parameters.Add(parameter); 

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.