Linq查询包含两个分组的子查询,一个具有平均值,另一个具有最大值

时间:2013-04-02 15:27:36

标签: linq

我有一个父表,parentTable,在childTable中可能有也可能没有子项。我希望得到任何给定父母子女的平均完成百分比,以及他们所在的孩子的MAX(到期)(日期)。我的SQL是这样的:

SELECT parentRecord_id, assigned_to,
    (SELECT avg(complete) 
    FROM childTable
    WHERE parent_id = parentRecord_id
    and deleted IS NULL
    GROUP BY parent_id),
    (SELECT max(due) 
    FROM childTable
    WHERE parent_id = parentRecord_id
    and deleted IS NULL
    GROUP BY parent_id
    )
FROM parentTable s
WHERE s.deleted IS NULL and assigned_to IS NOT NULL

我的结果集为我提供了具有正确值和最大值的行,或者为null。在这个例子中,我必须进行后续处理,所以如果我通过DataTable行进行foreach,我可以忽略空值。但是我试图在Linq中这样做,并且无法弄清楚如何避免System.InvalidOperationException,其中Linq试图将null转换为double。这是我到目前为止所尝试过的。

var query8 = from s in db.parentTable
    where s.deleted == null
    select new
        {
            ID = s.assigned_to,
            Average =
                ((from t in db.childTable
                      where t.parent_id == s.strategy_id
                      group t by new { t.parent_id } into g
                      select new
                          {
                             a0 = g.Average(f0 => f0.complete )
                          }).FirstOrDefault().a0) 
                       };
foreach (var itm in query8)
    {
        Console.WriteLine(String.Format("User id:{0}, Average: {1}", itm.ID, itm.Average));
    }

这是我的问题。如何获取查询来处理平均完成或最大到期(日期)为空的返回行?

4 个答案:

答案 0 :(得分:0)

您可以过滤掉值为空的记录(按其他条件),或者如果要包含它们,请执行以下操作:

a0 = g.Average(f0 => f0.complete.HasValue? f0.complete: 0 )

答案 1 :(得分:0)

我会在调用Average / Max之前将列表转换为可以为空的double:

var query8 = 
    from s in db.parentTable          
    where s.deleted == null
    select new
    {
      ID = s.assigned_to,
      Average =
        from t in db.childTable
        where t.parent_id == s.strategy_id
        group t by t.parent_id into g
        select g.Cast<double?>().Average(f0 => f0.complete)
    };

答案 2 :(得分:0)

假设complete是Nullable,你应该能够:

var query8 = from s in db.parentTable
    where s.deleted == null
    select new
        {
            ID = s.assigned_to,
            Average =
                ((from t in db.childTable
                      where t.parent_id == s.strategy_id
                         && s.complete.HasValue()
                      group t by new { t.parent_id } into g
                      select new
                          {
                             a0 = g.Average(f0 => f0.complete )
                          }).FirstOrDefault().a0) 
                       };

答案 3 :(得分:0)

感谢所有回复的人。

我无法解决基本查询的null匿名问题,但是在childTable中添加连接消除了空值。

另一个解决方案是在g.DefaultIfEmpty子句中使用from x。

var query8 =
    from st in db.tableParent
    select new { Ass = st.assigned_to ,
        Avg = 
        (from ta in db.tableChild
         group ta by ta.parent_id into g
         from x in g.DefaultIfEmpty()
         select g.Average((f0=>f0.complete))).FirstOrDefault()
     };