LINQ用于多次计数操作

时间:2012-01-04 20:13:08

标签: asp.net sql linq

@gfrizzle指出here LINQ to SQL在给定LINQ时为每个计数操作生成独立的SELECT语句:

From d in db
Group d.a.AuditStatus By d.a.DateCreated Into Group
Select _
    DateIssued = DateCreated, _
    TotalAudits = Group.Count(), _
    TotalCancelled = Group.Count(Function(x) If(x = "Cancelled", True, False)), _
    TotalComplete = Group.Count(Function(x) If(x = "Complete", True, False)), _
    TotalIssued = Group.Count(Function(x) If(x = "Issued", True, False)), _
    TotalPending = Group.Count(Function(x) If (x = "Pending", True, False)), _
    Remaining = 0

由于有问题的数据足够大,这很容易导致巨大的性能损失。我知道我可以将其重写为本机SQL查询,但我在其他地方使用LINQ的几个功能(比如能够破坏我的where子句),如果我可以避免它,我不想放弃它。还有其他解决方法吗?

2 个答案:

答案 0 :(得分:1)

尤里卡!我终于明白了。这是构建底层SQL的一个逻辑问题。 无法将LINQ写为单一传递SQL查询,因为COUNT操作只查看行数,而不管任何WHERE样式子句。

解决方案是使用SUM代替模拟COUNT / WHERE组合。此LINQ查询使用SUM(CASE WHEN)列创建单个传递SQL查询。

    From d In resultSet
    Group d By key = d.a.DateCreated Into g = Group
    Select _
        TotalAudits = g.Sum(Function(x) 1), _
        TotalCancelled = g.Sum(Function(x) If(x.a.AuditStatus = "Cancelled", 1, 0)), _
        TotalComplete = g.Sum(Function(x) If(x.a.AuditStatus = "Complete", 1, 0)), _
        TotalIssued = g.Sum(Function(x) If(x.a.AuditStatus = "Issued", 1, 0)), _
        TotalPending = g.Sum(Function(x) If(x.a.AuditStatus = "Pending", 1, 0)), _
        Remaining = 0

答案 1 :(得分:0)

也许如果您使用复合键运行另一个查询来获取子组,它可能会转换为更高效的SQL。我没有使用我的VB Linq语法,所以请考虑这个伪代码:

From d in db 
Group d.a.AuditStatus By New With { d.a.AuditStatus, d.a.DateCreated } Into Group 
Select ...