使用SQL / LINQ过滤具有特定功能列表的产品

时间:2012-09-23 14:22:08

标签: asp.net sql sql-server linq

经过数小时的谷歌搜索和搜索stackoverflow,我迫切需要你帮助解决Linq的问题。

想象一下两个表:

表A:产品

ID(int)     | ProductName(varchar(50))
1___________|_______________A
2___________|_______________B
3___________|_______________C
...

表B:ProductFeatures

ProductID(int)        | FeatureID(int)                | FeatureValue(smallint)
1_____________________|_________1_____________________|____________1
1_____________________|_________2_____________________|____________1  
1_____________________|_________3_____________________|____________0
2_____________________|_________1_____________________|____________0
2_____________________|_________2_____________________|____________1
3_____________________|_________1_____________________|____________1
3_____________________|_________2_____________________|____________1
...

E.g。

FeatureID = 1 => "has WiFi" 
FeatureValue 1 = Yes / 0 = No.

表C:我还有一个功能描述表

FeatureID int, 
FeatureName varchar(50)

在我的ASP应用程序中,我有一个包含复选框/下拉列表等控件的面板,允许用户过滤产品列表。

因此,如果有人选择“笔记本电脑”类别,该页面将显示笔记本电脑列表,此外,他还可以点击“带WiFi”复选框等过滤器,以缩小搜索范围。

我的问题:

首先,Filter控件填充一个包含所请求的FeatureID的List:

List<int> filters=getFilterPanelList(); 

如何从Products表中选择所有产品哪里的产品功能至少包含过滤器列表? (在SQL或Linq脚本中)。

例如:如果控件生成列表(1,3),则Linq查询将仅返回产品1,因为它至少包含1和3个FeatureID。

我发现类似于下面的SQL查询,但是'IN'运算符(或Linq中的'Contains'函数)返回包含FeatureID 1或FeatureID 3但不包含两者的所有产品:

SELECT ProductID 
FROM 
    Products P
    JOIN ProductFeatures PF ON PF.ProductID = P.ID
WHERE 
    PF.ProductID IN

SELECT ProductID 
FROM 
    ProductFeatures 
WHERE 
    FeatureID IN @FilterList)"

3 个答案:

答案 0 :(得分:0)

在Linq:

from p in products
where p.ProductFeatures.Count(pf => filters.Contains(pf.FeatureID)) == filters.Count
select p

我假设一个产品不超过一个相同类型的功能。

答案 1 :(得分:0)

在这种情况下,您希望获得具有这两种产品功能的产品。 所以我的sugession是修改你的sql:

  

SELECT distinct PF.ProductID
  来自产品P
  加入ProductFeatures PF   ON PF.ProductID = P.ID   在哪里PF.ProductID在   (   选择产品ID
  来自ProductFeatures
  WHERE FeatureID IN(@FilterList)   和FeatureValue = 1 - 添加此条件将确保所有功能都选择是   )

答案 2 :(得分:0)

非常感谢你的帮助......你的快速反应和你的好答案对我来说是一个真正的救星。

我将缓存这些表(使用SQLDataReader查询SQL Server并使用这两个表加载数据集),每次从Cache中检索它们时,我都会使用LINQ To DataSet ..

所以我修改了Relational Division案例的SQL脚本(来自tc.umn.edu/~hause011/code/SQLexample.txt)并制作了以下LINQ To DataSet脚本:

List<int> FilteredProductIDs = 
      (from p1 in Products where !filters.Any(l => !Products.Any(
      p2 => (p2.Field<int>("ProductID") == p1.Field<int>("ProductID"))
                                  && (p2.Field<int>("FeatureID") == l)))
                            select p1.Field<int>("ProductID")).ToList<int>();

我希望对有类似问题的其他人有用....再次感谢。