跨复杂父/子/父/子关系的 LINQ 查询

Posted

技术标签:

【中文标题】跨复杂父/子/父/子关系的 LINQ 查询【英文标题】:LINQ Query across complex parent/child/parent/child relationships 【发布时间】:2017-01-31 03:49:29 【问题描述】:

这对于 LINQ 专业人士来说可能是小菜一碟,但这超出了我的基本能力。我们有六个通过 Entity Framework 访问的表:

Stores  Storeid, Description 
ShoppingDays  ShoppingDayid, Date, Storeid 
Transactions  Transactionid, Amount, ShoppingDayid, PaintColorid 
PaintColors  PaintColorid 
DyeAllocations  DyeAllocationid, PaintColorid, Percent, DyeId 
Dyes  DyeId, Name 

Stores、ShoppingDays 和 Transactions 表很简单,不需要注释。但是,每笔交易都购买一种颜色的油漆。每种颜色的油漆都由混合的颜色染料百分比组成,加起来为 100%。

我想总结一下每家商店每天花在每种染料上的所有美元。想象一下 store1 在第 1 天有两笔交易。一笔 30 美元的交易用于购买紫色涂料(40% 红色、40% 蓝色、20% 黑色),另一笔交易以 20 美元购买粉色涂料(20% 红色、80% 白色)。结果看起来像

Store1,1,红色,16 美元 Store1,1,蓝色,12 美元 Store1,1,黑色,$6 Store1,1,白色,$16

任何帮助将不胜感激。我什至不确定从哪里开始。我对所有表进行了内部连接,然后将数据放入 excel 数据透视表中以提取数据。这显然是不正确的。

我从以下开始。它提供了一个表格,显示每笔交易的每笔染料购买。我想总结一下每个商店和购物日的购买情况,但我不确定如何。

var dyeValues = (from store in db.stores
                           join sd in db.shoppingdays on store.storeId equals sd.storeId
                           join tr in db.transactions on sd.shoppingdayId equals tr.shoppingdayId
                           join pc in db.paintcolors on tr.paintcolorId equals pc.paintcolorId
                           join da in db.dyeallocations on pc.paintcolorId equals da.paintcolorId
                           where da.percent > 0.0m
                           select new
                           
                               store.Description,
                               shoppingdayDate = sd.Date,
                               da.dye.Name,
                               da.percent,
                               Allocation = da.percent * tr.Amount
                           );

【问题讨论】:

Paintid.. 在哪里?这是哪里?另外,至少,与我们分享您的尝试…… 抱歉,PaintId 应该是 PaintColorId。老实说,我对所有表进行了平面内连接,然后使用 Excel 中的数据透视表提取了我想要的数据。除此之外,我一直从 db.stores.selectmany(st => st.shoppingdays).selectmany(sd => sd.transactions)... 等开始。但我知道这不是正确的方法。我应该从染料或油漆颜色开始,然后倒退吗? 嗨@jlear,Stackoveflow 不是一个你可以说我有这些数据的地方,我想要它。你需要在你身边表现出一些努力。请检查:***.com/help/how-to-ask 这是给提醒的,@bit。我已经研究了几个小时,查看了 groupby()、select()、selectmany()、sum() 等,但我对这种方法完全不知所措。当我认为我的努力完全是左场猜测时,我不确定如何展示我的努力。这不是缺乏努力,而是缺乏进步。 看看如何使用导航属性。您不需要这些连接。 【参考方案1】:

这里相当于经典的SQL方式。

首先是按ShoppingDayId, DyeId 分组并计算Sum(Percent * Amount) 的子查询:

var dyeAllocations =
    from tr in db.Transactions
    join pc in db.PaintColors on tr.PaintColorId equals pc.PaintColorId
    join da in db.DyeAllocations on pc.PaintColorId equals da.PaintColorId
    where da.Percent > 0.0m
    group new  Allocation =  da.Percent * tr.Amount 
    by new  tr.ShoppingDayId, da.DyeId  into g
    select new  g.Key.ShoppingDayId, g.Key.DyeId, Allocation = g.Sum(e => e.Allocation) ;

然后加入其他表以获取所需的附加信息:

var dyeValues =
    from da in dyeAllocations
    join dye in db.Dyes on da.DyeId equals dye.DyeId
    join sd in db.ShoppingDays on da.ShoppingDayId equals sd.ShoppingDayId
    join store in db.Stores on sd.StoreId equals store.StoreId
    select new
    
        store.Description,
        sd.Date,
        dye.Name,
        da.Allocation
    ;

子查询可以嵌入到实际查询中,我使用了一个单独的变量只是为了便于阅读(它对 EF 生成的 SQL 查询没有影响)。此外,您可能需要更新字段名称/大小写以匹配实际模型,但这应该会给您一些想法。

【讨论】:

谢谢伊万。我试试看。 钉了它伊万!我通过获取您的组语句并将其附加到我的加入来合并您的两个查询。它非常慢,但现在我知道如何对此进行分组。非常感谢!【参考方案2】:

我将 Ivan 的答案修改为一个查询。这很慢,但它有效!

var deyValues = from cs in account.stores
       join sd in db.shoppingdays on cs.storeId equals sd.storeId
       join tr in db.transactions on sd.shoppingdayId equals tr.shoppingdayId
       join pc in db.paintcolors on tr.paintcolorId equals pc.paintcolorId
       join da in db.dyeallocations on pc.paintcolorId equals da.paintcolorId
       where da.AfterTaxOptimalPortion > 0.0m
       group new  Allocation = da.Percent * tr.Amount 
       by new  AccountName = cs.Account.Name, ShoppingDate = sd.Date, DyeName = da.dye.Name  into g
       select new  g.Key.AccountName, g.Key.ShoppingDate, g.Key.DyeName, Total = g.Sum(el => el.Allocation) ;

【讨论】:

以上是关于跨复杂父/子/父/子关系的 LINQ 查询的主要内容,如果未能解决你的问题,请参考以下文章

通过子关系 ParseSwift 查询父级

DAO 最佳实践:查询父/子

linq依据传入数据集合查询相应子级数据

ES 父子文档查询

TP框架 mysql子查询

查询获取同一张表中1:N关系的数据