需要 EF 解决方法来只加载总数而不是每一行

问题描述 投票:0回答:1

以下查询运行无误。

var results = await query
    .GroupBy(
        t => new { t.Departure!.Value.Year, t.Departure!.Value.Month },
        t => new
        {
            Departure = t.Departure!.Value,
            Quantity = t.InboundQuantity + t.TruckRailcars.Sum(tr => tr.Quantity) + t.StorageTrucks.Sum(st => st.Quantity)
        })
    .ToListAsync();

但是,此查询返回大约 50,000 行。但我只需要总计,即 12 行。所以我尝试添加一个

Select()
子句。

var results = await query
    .GroupBy(
        t => new { t.Departure!.Value.Year, t.Departure!.Value.Month },
        t => new
        {
            Departure = t.Departure!.Value,
            Quantity = t.InboundQuantity + t.TruckRailcars.Sum(tr => tr.Quantity) + t.StorageTrucks.Sum(st => st.Quantity)
        })
    .Select(g => new { Date = g.Key, Quantity = g.Sum(t => t.Quantity) })
    .ToListAsync();

但这失败了。

Microsoft.Data.SqlClient.SqlException:“无法对包含聚合或子查询的表达式执行聚合函数。
无法对包含聚合或子查询的表达式执行聚合函数。
无法对包含聚合或子查询的表达式执行聚合函数。
无法对包含聚合或子查询的表达式执行聚合函数。'

我已经尝试了我能想到的所有变体,但没有运气。当我只需要总数时,接收所有 50,000 行的效率会非常低。这里有人有什么想法吗?

注意:

query
只是一个带有几个
Where()
子句的数据库表。

更新

如果有人好奇,这是由已接受的答案生成的查询。

SELECT [t5].[Year], [t5].[Month], COALESCE(SUM([t5].[Quantity]), 0.0E0) AS [Quantity]
FROM (
    SELECT [t0].[Year], [t0].[Month], COALESCE(SUM([t0].[InboundQuantity]), 0.0E0) AS [Quantity]
    FROM (
        SELECT [t].[InboundQuantity], DATEPART(year, [t].[Departure]) AS [Year], DATEPART(month, [t].[Departure]) AS [Month]
        FROM [Trucks] AS [t]
        INNER JOIN [Facilities] AS [f] ON [t].[FacilityId] = [f].[Id]
        INNER JOIN [Companies] AS [c] ON [f].[CompanyId] = [c].[Id]
        INNER JOIN [PurchaseOrders] AS [p] ON [t].[PurchaseOrderId] = [p].[Id]
        INNER JOIN [Products] AS [p0] ON [p].[ProductId] = [p0].[Id]
        WHERE [c].[CompanyCode] = @__companyCode_0 AND [t].[Departure] >= @__startMonth_1 AND [t].[Departure] < @__endMonth_2 AND [p0].[UnitOfMeasurement] = 0 AND [t].[FacilityId] = 1
    ) AS [t0]
    GROUP BY [t0].[Year], [t0].[Month]
    UNION ALL
    SELECT [t2].[Year], [t2].[Month], COALESCE(SUM([t2].[Quantity]), 0.0E0) AS [Quantity]
    FROM (
        SELECT [t4].[Quantity], DATEPART(year, [t3].[Departure]) AS [Year], DATEPART(month, [t3].[Departure]) AS [Month]
        FROM [Trucks] AS [t3]
        INNER JOIN [Facilities] AS [f0] ON [t3].[FacilityId] = [f0].[Id]
        INNER JOIN [Companies] AS [c0] ON [f0].[CompanyId] = [c0].[Id]
        INNER JOIN [PurchaseOrders] AS [p1] ON [t3].[PurchaseOrderId] = [p1].[Id]
        INNER JOIN [Products] AS [p2] ON [p1].[ProductId] = [p2].[Id]
        INNER JOIN [TruckRailcars] AS [t4] ON [t3].[Id] = [t4].[TruckId]
        WHERE [c0].[CompanyCode] = @__companyCode_0 AND [t3].[Departure] >= @__startMonth_1 AND [t3].[Departure] < @__endMonth_2 AND [p2].[UnitOfMeasurement] = 0 AND [t3].[FacilityId] = 1
    ) AS [t2]
    GROUP BY [t2].[Year], [t2].[Month]
    UNION ALL
    SELECT [t6].[Year], [t6].[Month], COALESCE(SUM([t6].[Quantity]), 0.0E0) AS [Quantity]
    FROM (
        SELECT [s].[Quantity], DATEPART(year, [t7].[Departure]) AS [Year], DATEPART(month, [t7].[Departure]) AS [Month]
        FROM [Trucks] AS [t7]
        INNER JOIN [Facilities] AS [f1] ON [t7].[FacilityId] = [f1].[Id]
        INNER JOIN [Companies] AS [c1] ON [f1].[CompanyId] = [c1].[Id]
        INNER JOIN [PurchaseOrders] AS [p3] ON [t7].[PurchaseOrderId] = [p3].[Id]
        INNER JOIN [Products] AS [p4] ON [p3].[ProductId] = [p4].[Id]
        INNER JOIN [StorageTrucks] AS [s] ON [t7].[Id] = [s].[TruckId]
        WHERE [c1].[CompanyCode] = @__companyCode_0 AND [t7].[Departure] >= @__startMonth_1 AND [t7].[Departure] < @__endMonth_2 AND [p4].[UnitOfMeasurement] = 0 AND [t7].[FacilityId] = 1
    ) AS [t6]
    GROUP BY [t6].[Year], [t6].[Month]
) AS [t5]
GROUP BY [t5].[Year], [t5].[Month]
c# .net .net-core entity-framework-core
1个回答
1
投票

您的查询应分为三部分,并在连接后再次分组。

var inbound =
    from t in query
    group t by new { t.Departure!.Value.Year, t.Departure!.Value.Month } into g
    select new 
    {
        g.Key,
        Quantity = g.Sum(x => x.InboundQuantity)
    };

var truckRailcars =
    from t in query
    from tr in t.TruckRailcars
    group tr by new { t.Departure!.Value.Year, t.Departure!.Value.Month } into g
    select new 
    {
        g.Key,
        Quantity = g.Sum(x => x.Quantity)
    };

var storageTrucks =
    from t in query
    from st in t.StorageTrucks
    group st by new { t.Departure!.Value.Year, t.Departure!.Value.Month } into g
    select new 
    {
        g.Key,
        Quantity = g.Sum(x => x.Quantity)
    };

var resultQuery = 
    from q in inbound.Concat(truckRailcars).Concat(storageTrucks)
    group q by q.Key into g
    select new 
    {
        Date = g.Key,
        Quantity = g.Sum(x => x.Quantity)
    };
© www.soinside.com 2019 - 2024. All rights reserved.