1

MyProductsというテーブルがあり、item1とitem2を返したいです。

SELECT item1, item2 from MyProducts

ただし、(C#から)渡した文字列配列でフィルタリングする必要があります。これは非常に大きなテーブルなので、「IN」ステートメントが出ています。joinステートメントを使用してこれを行うにはどうすればよいですか。ありがとう!

4

3 に答える 3

1

私はいつもこの方法が好きでした...

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 

その後、これを行うことができます...

CREATE PROCEDURE MySp
    @list varchar(max)
AS 

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

注:そこには多くの分割関数があるので、この特定の関数を使用する必要はありません。


SQL Server 2008を使用するときに使用した別の方法は、次のようなテーブルパラメーターを使用することです...

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

この方法で、C#からSQLServerにパラメーターを渡します。

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); 
于 2012-10-05T13:13:55.573 に答える
1

INステートメントが「アウト」である理由はありません。最終的に、これはフィルタリングの完全に合理的な方法です。オプティマイザにさまざまなオプションについて心配させます。それは確かにMyProducts大きいという事実によって影響を受けません。結合を追加すると、より多くの作業が行われます。ただし、「ヒット」の数や関連する作業が減少するわけではありません。たとえば、dapper でそれを行うには、次のようにします。

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

またはLINQを使用:

string[] filter = ...
var rows = db.Products.Where(x => filter.Contains(x.SomeField));
于 2012-10-05T13:12:31.507 に答える
1

1 つの解決策は、一時テーブルを作成して結合することです。一時テーブルは、結合する列にインデックスを持つことができます。

于 2012-10-05T12:57:33.867 に答える