Лучшая эффективность в сгруппированных счетчиках LINQ - PullRequest
0 голосов
/ 09 января 2020

Я пытаюсь создать запрос LINQ для представления в Microsoft Entity Framework Core . В моем случае у меня есть коллекция записей о автомобилях, которые я хочу создать для базовых аналитиков. Например,

  1. сколько автомобилей в коллекции?
  2. Сколько вариаций цвета автомобиля содержит коллекция
  3. Сколько вариаций капай двигателя автомобиля делает коллекция содержит
var result = Cars
    .AsQueryable()
    .GroupBy(car => 1)
    .Select(group => new
    {
        NoCars = group.Select(g => g.CarId).Count(),
        NoColours = group.Select(g => g.Colour).Distinct().Count(),
        NoYears = group.Select(g => g.YearOfManufacture).Distinct().Count()
    });

Хотя это работает и возвращает желаемый результат, сгенерированный SQL не кажется очень эффективным ...

-- Region Parameters
DECLARE @p0 Int = 1
DECLARE @p1 Int = 1

-- EndRegion
SELECT (
    SELECT COUNT(*)
    FROM (
        SELECT [t3].[Id]
        FROM [Cars] AS [t3]
        WHERE ([t2].[value] = @p1) AND (/* Filter Criteria */)
        ) AS [t4]
    ) AS [NoCars], (
    SELECT COUNT(*)
    FROM (
        SELECT DISTINCT [t5].[Colour]
        FROM [Cars] AS [t5]
        WHERE ([t2].[value] = @p1) AND (/* Filter Criteria */)
        ) AS [t6]
    ) AS [NoColours], (
    SELECT COUNT(*)
    FROM (
        SELECT DISTINCT [t7].[CapacityId]
        FROM [Cars] AS [t7]
        WHERE ([t2].[value] = @p1) AND (/* Filter Criteria */)
        ) AS [t8]
    ) AS [NoCapacities]
FROM (
    SELECT [t1].[value]
    FROM (
        SELECT @p0 AS [value]
        FROM [Cars] AS [t0]
        ) AS [t1]
    GROUP BY [t1].[value]
    ) AS [t2]

[Script как сгенерировано LinqPad]

Итак, на практике выполняется ряд полных подзапросов. В приведенном выше простом примере это может быть не слишком проблематично, но в моем приложении коллекция Cars будет определяться по различным критериям.

Я надеялся добиться более организованного запроса, такого как:

SELECT
   COUNT(*) AS NoCars
   ,COUNT(DISTINCT C.Colour) AS NoColours
   ,COUNT(DISTINCT C.CapacityID) AS NoCapacities
FROM Cars C
WHERE (
  /* filter criteria */
)

Есть ли способ улучшить мой оператор LINQ?

Спасибо.

...