如何在SQL/Net内核中进行产品复杂过滤

如何在SQL/Net内核中进行产品复杂过滤,sql,asp.net-core,filter,Sql,Asp.net Core,Filter,我有一个Net Core 2.2 Web应用程序,SQL Server 2017,Linq,Entity Core,SQLQuery FromSql 我需要为电子商务网站这样的产品做复杂的过滤器,在这些网站上,你可以按属性过滤笔记本电脑品牌:戴尔、惠普、内存:2GB、4GB 示例:Dell品牌或HP品牌,尺寸为S或XL 当我尝试在多属性选择后显示属性和产品数量计数值时出现问题,例如:选择2 GB或4 GB后显示Dell 4个项目 属性/过滤器: Brand - Dell (2 items) -

我有一个Net Core 2.2 Web应用程序,SQL Server 2017,Linq,Entity Core,SQLQuery FromSql

我需要为电子商务网站这样的产品做复杂的过滤器,在这些网站上,你可以按属性过滤笔记本电脑品牌:戴尔、惠普、内存:2GB、4GB

示例:Dell品牌或HP品牌,尺寸为S或XL

当我尝试在多属性选择后显示属性和产品数量计数值时出现问题,例如:选择2 GB或4 GB后显示Dell 4个项目

属性/过滤器:

Brand
- Dell (2 items)
- HP (3)

Memory
- 2 GB (2)
- 4 GB(3)

Display
- 17 inch (1)
- 19 inch ( 2)

因为不能在LINQ中实现这一点,所以必须使用字符串SQLQuery FromSql来完成

SQL数据库结构:

**Products** ( Ex: Laptop 1, Laptop 2 ) 
- ProductID

**Attributes** ( Ex: Memory, Brand ) 
- AttributeID

**AttributeValues** ( Ex: 2 Gb, Dell )
- AttributeValueID
- AttributeID ( foreign key )

**ProductAttributes** 
-ProductAttibuteID
-ProductID ( foreign key )
-AttributeID (  foreign key )
-AttributeValueID ( foreign key )

我试过一些东西,但不起作用不算好:


 public class Filter
    {
        public int AtributeID { get; set; }
        public int ?AtributeValueID { get; set; }       
    }


// Filters - list with selected attributes ( AtributeID ,AtributeValueID )

string SQLQuery = "SELECT AtributeValueID,Title,Importance,AtributeID , (select count (*) from Products p where p.ProductCategoryID ={0}";

foreach (var filtersGroup in Filters.GroupBy(p => p.AtributeID))
{
    int atributeID = filtersGroup.Key;
    var atributeValues = filtersGroup.Select(p => p.AtributeValueID).ToList();

    SQLQuery += "and exists ( select 1 from ProductAtributes pa where pa.ProductID=p.ProductID and  ((av.AtributeID = " + atributeID + " and pa.AtributeValueID = av.AtributeValueID) ";

    foreach (var atributeValueID in atributeValues)
    {
        SQLQuery += " or pa.AtributeValueID=" + atributeValueID;
    }

    SQLQuery += "))";
}

SQLQuery += ") as Count";

SQLQuery += " FROM AtributeValues av ";


var queryAtributesValuesResult = context.Query<AtributeValueDTO>()
.FromSql(SQLQuery)
.AsNoTracking()
.ToList();

Executed DbCommand (1,203ms)
SELECT AtributeValueID,Title,Importance,AtributeID, 
(
    select count (*) from Products p where 
        exists 
        ( 
            select 1 from ProductAtributes pa where pa.ProductID=p.ProductID  
                                                    and ((av.AtributeID = 15 and pa.AtributeValueID = av.AtributeValueID) or pa.AtributeValueID=130)        
        )            
        and exists 
        ( 
            select 1 from ProductAtributes pa where pa.ProductID=p.ProductID 
                                                    and  ((av.AtributeID = 27 and pa.AtributeValueID = av.AtributeValueID) or pa.AtributeValueID=273 or pa.AtributeValueID=325)
        )      
)as Count 
FROM AtributeValues av


您的ProductAttribute包含其他表中的所有列,请尝试此操作以获取产品 其中attr15=val130,attr27=273或325

select pa1.*, pa2.AtributeID, pa2.AtributeValueID
  , dense_rank() over (order by id pa1.ProductId) 
    + dense_rank() over (order by id pa1.ProductId desc) - 1 as productCount
from ProductAtributes pa1 
join ProductAtributes pa2 on pa1.ProductId = pa2.ProductId
  and pa1.AtributeID = 15 and pa1.AtributeValueID in (130) 
  and pa2.AtributeID = 27 and pa2.AtributeValueID in (273, 325)   
通常,您需要尽可能多的连接和请求的属性来恢复具有属性集关系的虚拟产品,然后根据需要应用属性谓词


EDIT添加了一个基于分析函数的表达式来计算产品。Sql server不支持中的DISTINCT选项。因此,我使用了密集排列,但它不支持所需的窗口帧,即无界前后之间的行,并且我使用了两个默认帧的总和,即pa1.ProductId前后的行。

LINQ非常适合动态构造复杂条件查询。显示您的实体。我使用SQL Server 2017。服务器在Azure中。是的,上下文是实体核心框架。是的,我知道Linq不能在这种情况下使用,这就是为什么我们的重点是写一个查询,一个视图,或者其他任何东西,但在SQL中,问题解决了吗?如果不是,用C显示你的实体,我会用LINQ给出一个解决方案。不,它没有解决。实体与数据库结构相同:Products Ex:Laptop 1,Laptop 2-ProductID属性Ex:Memory,Brand-AttributeID AttributeValue Ex:2 Gb,Dell-AttributeValueID-AttributeID外键ProductAttributes-ProductAttitButeId-ProductID外键-AttributeID外键-AttributeValueID外键谢谢。如何同时计算与过滤器相关的产品?我建议的数据库结构可以吗?我应该重组它吗?使用另一个临时表以更方便的方式重新构造数据以获得更高的性能?或者可能是SQL中的实体化视图或Json数据?任何建议都是很好的,你会发现谷歌搜索eav db设计有很多优点和缺点。我的经验法则是,除非绝对不可避免,否则不要走EAV之路。请参阅有关计数的更新。