2012-10-05 49 views
1

我有一個表叫我的產品,我想回到物品1和項目2SQL Server的SELECT語句過濾

SELECT item1, item2 from MyProducts 

不過,我希望它是一個字符串數組我通過在過濾(從C#)。這是一張非常大的桌子,所以我發了一條'IN'聲明。我將如何使用連接語句來做到這一點。謝謝!

+1

哪個版本的sql-server?如果您在2008年或更近的時候可以使用表值參數 – Steve

+0

您要過濾的列是否以任何方式索引(如果是,索引是什麼類型)?等待索引/類型,可以使用不同的搜索選項。 – newfurniturey

+0

我過濾的列沒有編入索引,它們只是作爲客戶名稱的varchars。是的,這是Sql server 2008 – Badmiral

回答

1

沒有理由IN陳述是「out」;最終,這是一個完全合理的過濾方式 - 讓優化者擔心各種選項。它肯定不會受到MyProducts大的事實的影響。添加聯接可以帶來更多的工作:但是,它不會減少「點擊數」或涉及的工作。例如,要做到這一點與短小精悍的只是:

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)); 
+0

OP沒有提及MyProducts或過濾器陣列的大小是否是問題。如果過濾器數組超過2000個項目(大約),SQL將開始窒息。否則,對於大多數情況,Contains是一個很好的解決方案。 –

+0

@Jim如果他們需要將2000個過濾器選項下載到服務器上進行單個選擇,那麼就存在一個問題 - 只是帶寬會讓它變得很糟糕;聽起來像是一個設計問題,如果是這樣的話 –

1

一個解決方案是創建一個臨時表並加入它。臨時表可以在要加入的列上有索引。

+0

我該怎麼做?不完全確定如何處理數組 – Badmiral

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 

注意:Th有很多拆分功能,所以你不必使用這個特定的功能。


我一直在使用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 

傳遞參數到SQL Server從C#這樣...

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);