代码之家  ›  专栏  ›  技术社区  ›  Ryan

到LINQ的复杂SQL子查询

  •  2
  • Ryan  · 技术社区  · 15 年前

    我有一个SQL查询,在Linq中是不可能实现的。

    select * from attribute_value t0
    where t0.attribute_value_id in
    (
        select t1.attribute_value_id from product_attribute_value t1
        where t1.product_attribute_id in
        (
            select t2.product_attribute_id from product_attribute t2
            where t2.product_id in
            (
                select product_id from product p, manufacturer m
                where p.manufacturer_id = m.manufacturer_id
                and m.name = 'manufacturer name'
            )
            and pa.attribute_id = 1207
        )
    )
    

    在代码的后面,还必须动态地执行WHERE子句。

    4 回复  |  直到 15 年前
        1
  •  4
  •   Denis Valeev    15 年前

    尝试使用 Linqer . 我记得写了一些非常复杂的东西。

    顺便说一句,您的查询并不那么复杂,您只是从产品转到其属性值。只需在键上进行大量连接,就完成了。

        2
  •  4
  •   Slaggg    15 年前

    我喜欢通过将查询的离散组件作为单个语句编写来组成LINQ查询。因为每个语句都是一个查询而不是一个结果,所以Linq将在运行时将这些语句组合成一个单独的SQL查询。

    以这种方式编写查询,对我来说,可以非常容易地阅读,而不会牺牲运行时数据库的性能,因为无论如何,Linq都会在运行时将其变成一个大查询。它将把下面查询中的包含转换为子选择。

    使用LinqPad查看生成的SQL——看到SQL Linq创建的结果可能非常有趣。

    注意结果本身就是一个查询。要实现它,请执行result.tolist();

    var productIds = from p in product
                     join m in manufacturer on p.manufacturer_id equals m.manufacturer_id
                     where m.name == 'manufacturer name'
                     select p.product_id;
    
    var productAttributeIds =  from pa in product_attribute
                               where productIds.Contains(pa.product_id)
                               select pa.product_attribute_id;
    
    var attributeValueIds = from pav in product_attribute_value
                            where productAttributeIds.Contains(pav.product_attribute_id)
                            select pav.attribute_value_id;
    
    result = from av in attribute_value
             where attributeValueIds.Contains(av.atttriute_value_id)
             select av;
    
        3
  •  1
  •   Rohrbs    15 年前

    我已经使用contains()方法成功地实现了“in”查询。例如:

    int[] ids = new int[] { 1, 4 };
    
    databasecontext.SomeTable.Where(s => ids.Contains(s.id));
    

    上面将返回ID为1或4的SomeTable中的所有记录。

    我相信您可以将contains()方法链接在一起。我知道这看起来是倒退的,但是从最里面的子选区开始,从那里开始你的出路。

        4
  •  1
  •   eglasius    15 年前

    取决于模型,但您应该能够这样做:

    var attributes =
        from t0 in db.AttributeValues
        where t0.ProductAttributeValues.Any( t1=> 
            t1.ProductAttribute.AttributeId == 1207 &&
            t1.ProductAttribute.Product.Manufacturers
                 .Any(m=> m.name == "manufacturer name")
        )
        select t0;
    

    另一种与查询/公正翻译方法相当相似的方法:

    var attributes =
        from t0 in db.AttributeValues
        where db.Product_Attribute_Values.Any(t1 => 
            db.Product_Attributes.Any(t2 =>
                t2.product_attribute_id == t1.product_attribute_id &&
                db.Products.Any(p=> 
                     p.product_id == t2.product_id &&
                     db.Manufacturers.Any(m=> 
                          m.manufacturer_id == p.manufacturer_id && 
                          m.name == "manufacturer name"
                     )
                ) &&
                t2.attribute_id = 1207
            ) &&
            t0.attribute_value_id == t1.attribute_value_id
         )
         select t0;