C#-如何在Linq中执行SUM()/ SUM()

时间:2019-05-01 14:00:23

标签: c# sql entity-framework linq

我正在尝试在C#应用程序中执行此SQL SELECT:

SELECT SUM( a.VALUE_A) / SUM( a.VALUE_B)
    FROM "TABLE" a
    WHERE DATE_COLUMN = to_date('12/05/2018', 'DD/MM/YYYY');

将此C#与LINQ代码一起使用:

dto.day = await database.Where(x => x.DATE_COLUMN.Date == date_filtered)
                        .SumAsync(x => (x.VALUE_A) / (x.VALUE_B));

但是抛出一个异常,称除数为零。因此,我尝试通过在SumAsync()方法中添加三元IF来处理它:

 dto.day = await database.Where(x => x.DATE_COLUMN.Date == date_filtered)
                         .SumAsync(x => x.VALUE_B == 0 ? 0 : (x.VALUE_A) / (x.VALUE_B));

但是最终结果与直接SQL结果不同:

SQL给出正确的结果,例如:86.25

C#给出了错误的结果:227.87

拜托,我在做什么错了?

2 个答案:

答案 0 :(得分:4)

操作顺序是关键。请尝试以下操作:

var values = database.Where(x => x.DATE_COLUMN.Date == date_filtered)
                     .Select(x => new {x.VALUE_A, x.VALUE_B}).ToList();
dto.day = values.Sum(s => s.VALUE_A) / values.Sum(s => s.VALUE_B);

编辑:

为清楚起见,这是细分。在查询中,您将VALUE_A的总和除以VALUE_B的总和。

在LINQ语句中,您要对每条记录的VALUE_A / VALUE_B的结果求和。

在我的回答中,我正在创建一个匿名对象,该对象仅获得VALUE_A和VALUE_B。然后,我将两者的总和相除。希望这是一个更好的解释。

答案 1 :(得分:1)

您得到错误的结果,因为Sum(a) / Sum(b)Sum(a / b)不同。你想要的是

(a1 + a2 + ... aN) / (b1 + b2 + ...bN)

获得的是

(a1 / b1 + a2 / b2 + ... aN / bN)

因此,要获得所需的结果,在LINQ中,通常需要对Sum或类似集合的结果进行2个GroupBy调用。由于查询是顶级查询,因此您可以执行2个数据库Sum查询并从中查询结果,也可以使用伪造的按常量分组技巧通过一个数据库查询来获取。像这样:

var query = db.Table
    .Where(e => e.DATE_COLUMN.Date == date_filtered)
    .GroupBy(e => 1) // <--
    .Select(g => new
    {
        SumA = g.Sum(e => e.VALUE_A), // <--
        SumB = g.Sum(e => e.VALUE_B), // <--
    })
    .Select(e => e.SumB == 0 ? 0 : e.SumA / e.SumB);

var result = await query.FirstOrDefaultAsync();