【问题标题】:Apache Ignite Group By Linq Query IssueApache Ignite Group By Linq 查询问题
【发布时间】:2021-03-06 10:46:40
【问题描述】:

我正在尝试连接三个缓存,其中两个是左外连接的,还有 group by 子句。使用下面的查询我遇到了奇怪的问题,生成的 sql 不正确。

var query = (from service in serviceCache
            join meetingService in meetingServiceCache.DefaultIfEmpty() on service.Value.ServiceId equals meetingService.Value.ServiceId
            join meeting in meetingCache.DefaultIfEmpty() on meetingService.Value.MeetingId equals meeting.Value.MeetingId
            group new { service, meeting } by service.Value.ServiceId into g
            select new {
               service.Value.ServiceId,
               lastMeeting = g.Select(x=>x.meeting.Value.CreatedDate).Max()
            }).ToCacheQueryable().GetFieldsQuery.Sql;

生成的查询如下所示

select _T0.SERVICEID,min(_T0.CreatedDate) from MEETINGSCHEMA.SERVICES as _T0
left outer join (select _T1.*,_T1.KEY,_T1.VAL from MEETINGSCHEMA.MEETINGSERVICE as _T1) as _T2 on (_T2.SERVICEID= _T0.SERVICEID)
left outer join (select _T3.*,_T3.KEY,_T3.VAL from MEETINGSCHEMA.MEETINGS as _T3) as _T4 on (_T4.MEETINGID= _T3.MEETINGID)
group by (_T0.SERVICEID)

在选定的列中,createdDate 应该从 _T4 引用中选择,但它总是从第一个表别名中选择,因此查询失败总是将 CreatedDate 报告为无效列。我怀疑 linq 到 sql 的转换有问题。

如果我做错了,请告诉我。此外,代码 sn-p 是手动输入的,没有智能感知,如果有错别字,请见谅。

【问题讨论】:

  • 我想知道为什么你在 SQL 中有min 而在查询中有Max
  • 对我来说看起来像一个错误。你能提供更多细节吗?理想情况下,一个最小的复制器。
  • @PavelTupitsyn,尝试在 CacheLinqTest.Functions.cs 文件中运行下面的代码,并检查生成的查询 this people.Join(orgs.Where(o => o.Key > 10), p => p.Value.OrganizationId, o => o.Key, (p, o) => new { p, o }) .GroupBy(x => xoValue.Name) .Select(g => new { Org = g.Key, AgeSum = g.Max(x => xpValue.Age) });
  • @PavelTupitsyn。将下面的代码放在 Apache.Ignite.Core.Tests.Cache.Query.Linq>CacheLinqTest>TestGroupBy var query = persons.Join(orgs.Where(o => o.Key > 10), p => p.Value.OrganizationId, o => o.Key, (p, o) => new { p, o }) .GroupBy(x => x.o.Value.Name) .Select(g => new { Org = g.Key, AgeSum = g.Max(x => x.p.Value.Age) }).ToCacheQueryable().GetFieldsQuery().Sql;
  • @tech2avinash 这似乎对我有用,SQL 看起来正确并且查询返回结果。

标签: c# linq ignite


【解决方案1】:

分组后,您只能选择Key 属性或聚合函数。 LEFT JOIN 也应该以不同的方式编写。

var query = 
   from service in serviceCache
   join meetingService in meetingServiceCache on service.Value.ServiceId equals meetingService.Value.ServiceId into j
   from meetingService in j.DefaultIfEmpty()
   join meeting in meetingCache on meetingService.Value.MeetingId equals meeting.Value.MeetingId into j
   from meeting in j.DefaultIfEmpty()
   group new { service, meeting } by service.Value.ServiceId into g
   select new 
   {
       ServiceId = g.Key,
       lastMeeting = g.Max(x => x.meeting.Value.CreatedDate)
   };

【讨论】:

  • 我刚验证过,还是不行。Apache ignite linq 翻译和传统的linq to sql有点不同。通过上述更改,生成的 sql 只是从 sql 中省略了 meetingService 和会议缓存。
  • 也许是时候发现你用过的库了?如果需要,请自行添加.ToCacheQueryable().GetFieldsQuery.Sql;。
【解决方案2】:

这似乎是 Ignite 中的一个错误,我已经提交了 ticket。

解决方法是重新排序连接的表并将meeting 放在首位,如下所示:

var query = (from meeting in meetingCache
            join meetingService in meetingServiceCache.DefaultIfEmpty() on meeting.Value.MeetingId equals meetingService.Value.MeetingId
            join service in serviceCache service.Value.ServiceId equals meetingService.Value.ServiceId
            group new { service, meeting } by service.Value.ServiceId into g
            select new {
               service.Value.ServiceId,
               lastMeeting = g.Select(x=>x.meeting.Value.CreatedDate).Max()
            }).ToCacheQueryable().GetFieldsQuery.Sql;

另一种解决方法是对此查询使用原始 SQL。

【讨论】:

  • 更新到 2.10.0 后仍然遇到同样的问题
  • @tech2avinash 很有趣,你能提供更多细节吗?原来的reproducer在2.10上正常工作(分布式连接有错误,但是生成的SQL正确)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-02-16
  • 2017-02-11
  • 1970-01-01
  • 2018-07-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多