-
Notifications
You must be signed in to change notification settings - Fork 3.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Query: Translate GroupBy constant value with aggregate #9969
Comments
I would expect that the given linq query: var query = context.Orders.Where(o => (o.OrderId > 0))
.GroupBy(Param_0 => 0)
.Select(Param_1 => new {
P0 = Param_1.Key,
P1 = Param_1.Count(),
P2 = Param_1.Sum(elem => elem.Freight),
P3 = Param_1.Max(elem => elem.ShipName),
P4 = Param_1.Min(elem => elem.ShipAddress)
}); would group by the value '0' iff the database can do that and not by the first column as suggested by the author. So the linq query given could translate to the following sql when using postgres as the database: WITH TMP AS (
SELECT * FROM (VALUES (0)) AS t (key)
)
SELECT t1.KEY, COUNT(*), SUM(t2.Freight), MAX(t2.ShipName), MIN(t2.ShipAddress) FROM TMP t1
INNER JOIN "TABLE" AS t2 ON 1 = 1
GROUP BY t1.KEY The proposal is rather a hack and thus in my opinion this enhancement should be closed as invalid since a working implementation of the linq query could be: var query = context.Orders.Where(o => (o.OrderId > 0))
.GroupBy(Param_0 => Param_0.CustomerId)
.Select(Param_1 => new {
P0 = Param_1.Key,
P1 = Param_1.Count(),
P2 = Param_1.Sum(elem => elem.Freight),
P3 = Param_1.Max(elem => elem.ShipName),
P4 = Param_1.Min(elem => elem.ShipAddress)
}); |
@dpsenner - The second linq query posted already translate correctly to server. |
So we both agree that this issue is invalid because linq does not support column references by ordinal (i.e. |
The Linq & SQL query in first post are not same. The SQL is not the translation of the Linq, it is just an example of that
GroupBy constant is perfectly valid linq query and it is being generated by various frameworks already. > var a = new[] { 1, 2, 3 }.AsQueryable().GroupBy(t => 0).ToList();
> a
List<IGrouping<int, int>>(1) { Lookup<int, int>.Grouping { 1, 2, 3 } } This issue specifically to translate GroupBy constant in LINQ to something which is valid in database and gives same results. |
Has |
@asfernandes - |
Ok, so it does not treat 0 as an position. So translating to It should not be valid to do a equivalent to I'm not understanding why this should be complicate in LINQ. |
Group by constant works in EF 6 by using constant as the key column, similar to:
This seems like the logical translation of group by constant anyway. |
Pulling this back into 2.1 milestone. I got it working. |
- Add support for translating OrderBy after GroupBy operator - Add support for `HAVING` clause in SQL which would be generated when translating predicate after GroupByAggregate Resolves #10870 - Make sure client eval warning is not issued when translating GroupByAggregate Resolves #11157 - GroupBy Aggregate works when key/element/result selector is DTO instead of anonymous type Resolves #11176 - Make sure that SQL added to GROUP BY clause is not aliased Resolves #11218 - Translate GroupBy Constant/Parameter with aggregates Resolves #9969 Part of #10012
- Add support for translating OrderBy after GroupBy operator - Add support for `HAVING` clause in SQL which would be generated when translating predicate after GroupByAggregate Resolves #10870 - Make sure client eval warning is not issued when translating GroupByAggregate Resolves #11157 - GroupBy Aggregate works when element/result selector is DTO instead of anonymous type Resolves #11176 (KeySelector has to be client evaluated) - Make sure that SQL added to GROUP BY clause is not aliased Resolves #11218 - Translate GroupBy Constant/Parameter with aggregates Resolves #9969 Part of #10012 Part of #2341
- Add support for translating OrderBy after GroupBy operator - Add support for `HAVING` clause in SQL which would be generated when translating predicate after GroupByAggregate Resolves #10870 - Make sure client eval warning is not issued when translating GroupByAggregate Resolves #11157 - GroupBy Aggregate works when element/result selector is DTO instead of anonymous type Resolves #11176 (KeySelector has to be client evaluated) - Make sure that SQL added to GROUP BY clause is not aliased Resolves #11218 - Translate GroupBy Constant/Parameter with aggregates Resolves #9969 Part of #10012 Part of #2341
- Add support for translating OrderBy after GroupBy operator - Add support for `HAVING` clause in SQL which would be generated when translating predicate after GroupByAggregate Resolves #10870 - Make sure client eval warning is not issued when translating GroupByAggregate Resolves #11157 - GroupBy Aggregate works when element/result selector is DTO instead of anonymous type Resolves #11176 (KeySelector has to be client evaluated) - Make sure that SQL added to GROUP BY clause is not aliased Resolves #11218 - Translate GroupBy Constant/Parameter with aggregates Resolves #9969 Part of #10012 Part of #2341
We translate context.Orders.GroupBy(o => 2).Select(
g =>
new
{
Sum = g.Sum(o => o.OrderID),
Min = g.Min(o => o.OrderID),
g.Key,
Max = g.Max(o => o.OrderID),
Avg = g.Average(o => o.OrderID)
}) SELECT SUM([t].[OrderID]) AS [Sum], MIN([t].[OrderID]) AS [Min], [t].[Key], MAX([t].[OrderID]) AS [Max], AVG(CAST([t].[OrderID] AS float)) AS [Avg]
FROM (
SELECT [o].*, 2 AS [Key]
FROM [Orders] AS [o]
) AS [t]
GROUP BY [t].[Key] Same happens when grouping is by a variable from closure. |
We are experiencing this issue using EF Core 2.1:
Using SQL Server 2012.
The intention is to return one result containing aggregate date, which is why According to information i've found in some issues this should be possible since 2.1, so is there a bug here or are we doing something wrong? Or is there another way to return one result? |
@SamVanheer - That is #11976 Currently, we still do streaming group by for such queries. |
Thanks for the quick reply, we'll use separate queries for the time being until this can be done directly. |
@SamVanheer - You can rewrite your query to use element selector and get it to server eval var conversationTime = db.Conversations
.GroupBy(c => 1,
e =>
EF.Functions.DateDiffMillisecond(e.StartDate, e.EndDate) / 1000.0)
.Select(g =>
new
{
Name = "ConversationTime",
AverageTime = g.Average(c => c),
ShortestTime = g.Min(c => c),
LongestTime = g.Max(c => c)
}).ToList(); Produces SELECT AVG(CAST([t].[c] AS float)) AS [AverageTime], MIN([t].[c]) AS [ShortestTime], MAX([t].[c]) AS [LongestTime]
FROM (
SELECT DATEDIFF(MILLISECOND, [c].[StartDate], [c].[EndDate]) / 1000E0 AS [c], 1 AS [Key]
FROM [Conversations] AS [c]
) AS [t]
GROUP BY [t].[Key] |
Thanks for the help, this works. Here's the query we're using, slightly modified:
|
Based on #2341 (comment) & #2341 (comment)
Queries like above cannot be translated to relational group by since group by constant is invalid SQL
throws
Since the purpose of such queries is just to get full aggregate of whole table rather than group-wise, we can perhaps rewrite QueryModel to simplify the task beforehand so our translation pipeline can work seamlessly.
As indicated by @bricelam , some of the frameworks are generating such queries (he can fill in more details), hence we should separately prioritize that work, hence filing this issue.
The text was updated successfully, but these errors were encountered: