Запросы, сгенерированные группой по групповому соединению - PullRequest
2 голосов
/ 08 июля 2010

У меня есть следующая группа по выражению linq

from c in Categories
join p in Products on c equals p.Category into ps
select new { Category = new {c.CategoryID, c.CategoryName}, Products = ps };

Однако при этом генерируется следующий левый запрос внешнего соединения и возвращаются все категории, даже если с ними не связано ни одного продукта.

SELECT [t0].[CategoryID], [t0].[CategoryName], [t1].[ProductID], [t1].[ProductName],     [t1].[SupplierID], [t1].[CategoryID] AS [CategoryID2], [t1].[QuantityPerUnit],   [t1].[UnitPrice], [t1].[UnitsInStock], [t1].[UnitsOnOrder], [t1].[ReorderLevel], [t1].[Discontinued], (
    SELECT COUNT(*)
    FROM [Products] AS [t2]
    WHERE [t0].[CategoryID] = [t2].[CategoryID]
    ) AS [value]
FROM [Categories] AS [t0]
LEFT OUTER JOIN [Products] AS [t1] ON [t0].[CategoryID] = [t1].[CategoryID]
ORDER BY [t0].[CategoryID], [t1].[ProductID]

Что я действительно хочу, так это возвращать только те категории, которые имеют связанные продукты.Но если я перезапишу запрос linq следующим образом:

from c in Categories
join p in Products on c equals p.Category
group p by new {c.CategoryID, c.CategoryName} into ps
select new { Category = ps.Key, Products = ps };

Это даст мне желаемый результат, но запрос будет сгенерирован для каждой категории :

SELECT [t0].[CategoryID], [t0].[CategoryName]
FROM [Categories] AS [t0]
INNER JOIN [Products] AS [t1] ON [t0].[CategoryID] = [t1].[CategoryID]
GROUP BY [t0].[CategoryID], [t0].[CategoryName]
GO

-- Region Parameters
DECLARE @x1 Int SET @x1 = 1
DECLARE @x2 NVarChar(9) SET @x2 = 'Beverages'
-- EndRegion
SELECT [t1].[ProductID], [t1].[ProductName], [t1].[SupplierID], [t1].[CategoryID],  [t1].[QuantityPerUnit], [t1].[UnitPrice], [t1].[UnitsInStock], [t1].[UnitsOnOrder], [t1].[ReorderLevel], [t1].[Discontinued]
FROM [Categories] AS [t0]
INNER JOIN [Products] AS [t1] ON [t0].[CategoryID] = [t1].[CategoryID]
WHERE (@x1 = [t0].[CategoryID]) AND (@x2 = [t0].[CategoryName])
GO

-- Region Parameters
DECLARE @x1 Int SET @x1 = 2
DECLARE @x2 NVarChar(10) SET @x2 = 'Condiments'
-- EndRegion
SELECT [t1].[ProductID], [t1].[ProductName], [t1].[SupplierID], [t1].[CategoryID], [t1].[QuantityPerUnit], [t1].[UnitPrice], [t1].[UnitsInStock], [t1].[UnitsOnOrder], [t1].[ReorderLevel], [t1].[Discontinued]
FROM [Categories] AS [t0]
INNER JOIN [Products] AS [t1] ON [t0].[CategoryID] = [t1].[CategoryID]
WHERE (@x1 = [t0].[CategoryID]) AND (@x2 = [t0].[CategoryName])
GO

...

Есть ли способ сделать эквивалент внутреннего соединения и группы с помощью и все еще производить только один запрос, такой как групповое соединение?

Ответы [ 2 ]

3 голосов
/ 16 июля 2010
var queryYouWant =
  from c in Categories 
  join p in Products on c equals p.Category
  select new {Category = c, Product = p};

var result =
  from x in queryYouWant.AsEnumerable()
  group x.Product by x.Category into g
  select new { Category = g.Key, Products = g }; 

Есть ли способ сделать эквивалент внутреннего объединения и группировки и, тем не менее, произвести только один запрос, такой как групповое соединение?

Нет. Когда вы говорите, что GroupBy сопровождается неагрегированным доступом к элементам группы, это повторный запрос с ключом группы в качестве фильтра.

2 голосов
/ 09 июля 2010

Какова цель этого объединения?

Ваш оригинальный запрос идентичен этому:

from c in Categories
select new { Category = new { c.CategoryID, c.CategoryName }, c.Products }

Я что-то упускаю что-то очевидное ???

Если вам нужны только категории с продуктами, сделайте это:

from c in Categories
where c.Products.Any()
select new { Category = new { c.CategoryID, c.CategoryName }, c.Products }

Или, если вы хотите сгладить результаты:

from p in Products
select new { p, p.Category.CategoryID, p.Category.CategoryName }

Последнее будет переводиться во внутреннее или внешнее объединение - в зависимости от того, являются ли эти отношения недействительными. Вы можете форсировать эквивалент внутреннего соединения следующим образом:

from p in Products
where p.Category != null
select new { p, p.Category.CategoryID, p.Category.CategoryName }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...