question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

GroupBy inside Select produces wrong SQL

See original GitHub issue

Steps to reproduce

Create a query with a GroupBy on a navigational property inside a select statement.

await db.sessions
    .Include(s => s.answers)
    .Select(s => s.answers.GroupBy(a => a.identifier).Count())
    .ToListAsync();
Program.cs
using System;
using System.Diagnostics;
using System.Linq;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;

namespace IssueConsoleTemplate
{
    public class Session
    {
        public int id { get; set; }
        public DateTime date { get; set; }
        public IEnumerable<Answer> answers { get; set; }
    }

    public class Answer
    {
        public int id { get; set; }
        public string identifier { get; set; }
        public int sessionId { get; set; }
    }

    public class Context : DbContext
    {
        public DbSet<Session> sessions { get; set; }
        public DbSet<Answer> answers { get; set; }

        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        {
            var connectionString = "server=127.0.0.1;port=3306;user=root;password=;database=Issue1678";
            var serverVersion = ServerVersion.AutoDetect(connectionString);

            optionsBuilder
                .UseMySql(connectionString, serverVersion)
                .UseLoggerFactory(
                    LoggerFactory.Create(
                        b => b
                            .AddConsole()
                            .AddFilter(level => level >= LogLevel.Information)))
                .EnableSensitiveDataLogging()
                .EnableDetailedErrors();
            //optionsBuilder.UseInMemoryDatabase("Issue1678");
        }

        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            modelBuilder.Entity<Session>(
                entity =>
                {
                    entity.HasData(
                        new Session
                        {
                            id = 1,
                            date = DateTime.Now
                        });
                });

            modelBuilder.Entity<Answer>(
                entity =>
                {
                    entity.HasData(
                        new Answer
                        {
                            id = 1,
                            sessionId = 1,
                            identifier = "test"
                        });
                });
        }
    }

    internal static class Program
    {
        private static void Main()
        {
            using var context = new Context();

            context.Database.EnsureDeleted();
            context.Database.EnsureCreated();

            var result = context.sessions
                .Include(s => s.answers)
                .Select(s => s.answers.GroupBy(a => a.identifier).Count())
                .ToList();

            Console.WriteLine(string.Join(",", result));
        }
    }
}

The issue

A query like the one above produces the following SQL. I believe the problem is that the alias ‘s’ is not available and the inner clause is missing a JOIN statement.

SELECT (
    SELECT COUNT(*)
    FROM (
        SELECT `a`.`identifier`
        FROM `answers` AS `a`
        WHERE `s`.`id` = `a`.`sessionId`
        GROUP BY `a`.`identifier`
    ) AS `t`
)
FROM `sessions` AS `s`

The exception details are as follows.

An exception occurred while iterating over the results of a query for context type 'IssueConsoleTemplate.Context'.

MySqlConnector.MySqlException (0x80004005): Unknown column 's.id' in 'where clause'
  at MySqlConnector.Core.ResultSet.ReadResultSetHeaderAsync(IOBehavior ioBehavior) in /_/src/MySqlConnector/Core/ResultSet.cs:line 44
  at MySqlConnector.MySqlDataReader.ActivateResultSet(CancellationToken cancellationToken) in /_/src/MySqlConnector/MySqlDataReader.cs:line 127
  at MySqlConnector.MySqlDataReader.CreateAsync(CommandListPosition commandListPosition, ICommandPayloadCreator payloadCreator, IDictionary`2 cachedProcedures, IMySqlCommand command, CommandBehavior behavior, Activity activity, IOBehavior ioBehavior, CancellationToken cancellationToken) in /_/src/MySqlConnector/MySqlDataReader.cs:line 456
  at MySqlConnector.Core.CommandExecutor.ExecuteReaderAsync(IReadOnlyList`1 commands, ICommandPayloadCreator payloadCreator, CommandBehavior behavior, Activity activity, IOBehavior ioBehavior, CancellationToken cancellationToken) in /_/src/MySqlConnector/Core/CommandExecutor.cs:line 56
  at MySqlConnector.MySqlCommand.ExecuteReaderAsync(CommandBehavior behavior, IOBehavior ioBehavior, CancellationToken cancellationToken) in /_/src/MySqlConnector/MySqlCommand.cs:line 330
  at MySqlConnector.MySqlCommand.ExecuteDbDataReader(CommandBehavior behavior) in /_/src/MySqlConnector/MySqlCommand.cs:line 272
  at Microsoft.EntityFrameworkCore.Storage.RelationalCommand.ExecuteReader(RelationalCommandParameterObject parameterObject)
  at Microsoft.EntityFrameworkCore.Query.Internal.SingleQueryingEnumerable`1.Enumerator.InitializeReader(Enumerator enumerator)
  at Pomelo.EntityFrameworkCore.MySql.Storage.Internal.MySqlExecutionStrategy.Execute[TState,TResult](TState state, Func`3 operation, Func`3 verifySucceeded)
  at Microsoft.EntityFrameworkCore.Query.Internal.SingleQueryingEnumerable`1.Enumerator.MoveNext()

Further technical details

MySQL version: 5.7.36 Operating system: Windows 11 Pomelo.EntityFrameworkCore.MySql version: 6.0.1 Microsoft.AspNetCore.App version: 6.0.6

Issue Analytics

  • State:open
  • Created a year ago
  • Comments:5

github_iconTop GitHub Comments

1reaction
smitpatelcommented, Jun 28, 2022

From T-SQL perspective it is valid SQL. You can use any of the top level aliases from table inside any level nesting in the projection subqueries. So this could be just database specific limitations in terms of generated SQL. Do you have any alternate translation for the LINQ query?

0reactions
mguinnesscommented, Jun 28, 2022

It looks like MySQL added support in 8.0.14, see Supporting all kinds of outer references in derived tables. For earlier versions the generated SQL will need to be changed.

Read more comments on GitHub >

github_iconTop Results From Across the Web

SQL Group by returning wrong results
I have a salary table in which I am trying to return determine the lowest salary earned and by which industry for each...
Read more >
7 Common GROUP BY Errors
1. Forgetting GROUP BY with Aggregate Functions · 2. Confusing WHERE and HAVING · 3. Listing a Column Inside SELECT but Not in...
Read more >
GROUP BY gives wrong result with MIN() aggregate function
I want min price from table in each code. I tried using the following query: select id, code, category, mq, weight, weave, price,...
Read more >
An overview of the SQL GROUP BY clause
The SQL GROUP BY clause arranges similar data stored within one or several columns into groups, where an aggregate function is applied to...
Read more >
When using GROUP BY, do we always have to ...
No, the SQL query SELECT name, downloads FROM fake_apps GROUP BY price; is not valid because the GROUP BY clause is grouping the...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found