-
Notifications
You must be signed in to change notification settings - Fork 3.3k
Closed as not planned
Closed as not planned
Copy link
Description
Count(x => somePredicate)
is being translated as a subquery at the moment (EF6). If somePredicate
is merely a scalar computation over x
(and really whatever else is in scope at that point) EF can use a much better SQL pattern:
SUM(IIF(somePredicate, 1, 0))
(Or anything equivalent).
The same ideas applies to conditional sums:
grouping.Where(x => p(x)).Sum(x => s(x))
Should become:
grouping.Sum(x => p(x) ? s(x) : 0)
Another rewrite:
grouping.Select(x => f(x)).Sum(x => s(x))
Should become:
grouping.Sum(x => s(f(x)))
I don't see how those rewrites could ever do harm. They should be applies successively until everything has been moved into the sum or count. The rewrites should be added to make conditional counts and sum, even over computed values, a lot more efficient.
Test query:
var results = (from o in db.Orders
group o by o.CustomerID into g
select new
{
CustomerID = g.Key,
Count = g.Count(x => x.ID >= 0),
}).ToList();
SQL:
SELECT
[Distinct1].[CustomerID] AS [CustomerID],
(SELECT
COUNT(1) AS [A1]
FROM [dbo].[Orders] AS [Extent2]
WHERE ([Distinct1].[CustomerID] = [Extent2].[CustomerID]) AND ([Extent2].[ID] >= 0)) AS [C1]
FROM ( SELECT DISTINCT
[Extent1].[CustomerID] AS [CustomerID]
FROM [dbo].[Orders] AS [Extent1]
) AS [Distinct1]
Model:
public class Customer
{
public int ID { get; set; }
public string Name { get; set; }
public bool? HasFreeShipping { get; set; }
public virtual IList<Order> Orders { get; set; }
}
public class Order
{
public int ID { get; set; }
public int CustomerID { get; set; }
public Customer Customer { get; set; }
public DateTime CreateDateTime { get; set; }
}
Metadata
Metadata
Assignees
Labels
No labels