C# LINQ 查询 (MYSQL EF) - 不同记录和最新记录

发布于 2024-12-02 03:33:08 字数 1135 浏览 2 评论 0原文

我有一张桌子,我们称之为记录。包含: ID(整数)| CustID(整数)|时间(日期时间)|数据 (varchar)

我需要每个客户的最新(最新)记录:

SQL

select * from record as i group by i.custid having max(id);

LINQ 版本 1

dgvLatestDistinctRec.DataSource = from g in ee.Records
                                  group g by g.CustID into grp
                                  select grp.LastOrDefault();

这会引发错误:

System.NotSupportedException 未由用户代码 Message=LINQ 处理 实体无法识别方法“Faizan_Kazi_Utils.Record” 最后或默认[记录 ](System.Collections.Generic.IEnumerable`1[Faizan_Kazi_Utils.Record ])'方法,并且该方法不能翻译成store 表达。来源=System.Data.Entity

LINQ 版本 2

var list = (from g in ee.Records
            group g by g.CustID into grp
            select grp).ToList();
Record[] list2 = (from grp in list
                  select grp.LastOrDefault()).ToArray();
dgvLatestDistinctRec.DataSource = list2;

这可以工作,但效率很低,因为它将数据库中的所有记录加载到内存中,然后仅提取每个组的最后一个(最新成员)。

是否有任何 LINQ 解决方案可以达到上述 SQL 解决方案的效率和可读性?

I have a table, lets call it Record. Containing:
ID (int) | CustID (int) | Time (datetime) | Data (varchar)

I need the latest (most recent) record for each customer:

SQL

select * from record as i group by i.custid having max(id);

LINQ version 1

dgvLatestDistinctRec.DataSource = from g in ee.Records
                                  group g by g.CustID into grp
                                  select grp.LastOrDefault();

This throws an error:

System.NotSupportedException was unhandled by user code Message=LINQ
to Entities does not recognize the method 'Faizan_Kazi_Utils.Record
LastOrDefault[Record
](System.Collections.Generic.IEnumerable`1[Faizan_Kazi_Utils.Record
])' method, and this method cannot be translated into a store
expression. Source=System.Data.Entity

LINQ version 2

var list = (from g in ee.Records
            group g by g.CustID into grp
            select grp).ToList();
Record[] list2 = (from grp in list
                  select grp.LastOrDefault()).ToArray();
dgvLatestDistinctRec.DataSource = list2;

This works, but is inefficient because it loads ALL records from the database into memory and then extracts just the last (most recent member) of each group.

Is there any LINQ solution that approaches the efficiency and readability of the mentioned SQL solution?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

-柠檬树下少年和吉他 2024-12-09 03:33:08

更新:

var results = (from rec in Record group rec by rec.CustID into grp 
    select new
    {
        CustID = grp.Key,
        ID = grp.OrderByDescending(r => r.ID).Select(x => x.ID).FirstOrDefault(),
        Data = grp.OrderByDescending(r => r.ID).Select(x => x.Data).FirstOrDefault()
    }
);

所以我做了一个测试表并写了一个 Linq -> SQL 查询将完全满足您的需要。看看这个,让我知道你的想法。唯一要记住的是,如果此查询是缩放的,我相信它将在 select new 中分组后对每个 CustID 记录运行对数据库的查询。唯一可以确定的方法是在运行查询以获取信息时运行 SQL Tracer。http://www.foliotek.com/devblog/tuning-sql-server-for-programmers/

原文:

你能做这样的事情吗? from g in ee.Records where g.CustID == (from x in ee.Records where (g.CustID == x.CustID) && (g.ID == x.Max(ID)) .Select(r => r.CustID))

这都是伪代码,但希望您能明白。

Update:

var results = (from rec in Record group rec by rec.CustID into grp 
    select new
    {
        CustID = grp.Key,
        ID = grp.OrderByDescending(r => r.ID).Select(x => x.ID).FirstOrDefault(),
        Data = grp.OrderByDescending(r => r.ID).Select(x => x.Data).FirstOrDefault()
    }
);

So I made a test table and wrote a Linq -> SQL Query that will do exactly what you need. Take a look at this and let me know what you think. Only thing to keep in mind if this query is scaled I believe it will run a query to the DB for each and every CustID record after the grouping in the select new. The only way to be sure would be to run SQL Tracer when you run the query for info on that go here .. http://www.foliotek.com/devblog/tuning-sql-server-for-programmers/

Original:

Could you do something like this? from g in ee.Records where g.CustID == (from x in ee.Records where (g.CustID == x.CustID) && (g.ID == x.Max(ID)).Select(r => r.CustID))

That's all pseudo code but hopefully you get the idea.

青萝楚歌 2024-12-09 03:33:08

我可能来不及帮助解决您的问题,但我遇到了类似的问题,并且能够通过如下查询获得所需的结果:

from g in ee.Records
group g by g.CustID into grp
from last in (from custRec in grp where custRec.Id == grp.Max(cr => cr.Id) select custRec)
select last

I'm probably too late to help with your problem, but I had a similar issue and was able to get the desired results with a query like this:

from g in ee.Records
group g by g.CustID into grp
from last in (from custRec in grp where custRec.Id == grp.Max(cr => cr.Id) select custRec)
select last
沦落红尘 2024-12-09 03:33:08

如果用简单的 Last() 替换 LastOrDefault() 会怎样?
(是的,你必须检查你的记录表不为空)

因为我看不出MySQL如何返回你的“默认”组。这不是简单翻译成SQL就可以的事情。

What if you replace LastOrDefault() with simple Last()?
(Yes, you will have to check your records table isn't empty)

Because I can't see a way how MySQL can return you "Default" group. This is not the thing that can be simply translated to SQL.

深海夜未眠 2024-12-09 03:33:08

我认为 grp.LastOrDefault() 这个 C# 函数是 SQL 不知道的。 LINQ 将您的查询转换为 SQL 查询,以便数据库服务器理解。您可能想尝试创建一个存储过程,或者使用其他方法来过滤掉您要查找的内容。

第二个查询有效的原因是 LINQ to SQL 返回一个列表,然后您在 C# 列表上执行 LINQ 查询(以过滤出您需要的内容),该列表实现 IEnumerable/IQueryable 接口并理解 grp.LastOrDefault() 。

I think grp.LastOrDefault(), a C# function, is something that SQL doesn't know about. LINQ turns your query into an SQL query for your db server to understand. You might want to try and create an stored procedure instead, or another way to filter out what your looking for.

The reason your second query works is because the LINQ to SQL returns a list and then you do a LINQ query (to filter out what you need) on a C# list, which implements the IEnumerable/IQueryable interfaces and understands the grp.LastOrDefault().

眼睛会笑 2024-12-09 03:33:08

我有另一个想法:

// Get a list of all the id's i need by:
// grouping by CustID, and then selecting Max ID from each group.
var distinctLatest = (from x in ee.Records
                          group x by x.CustID into grp 
                          select grp.Max(g => g.id)).ToArray();

// List<Record> result = new List<Record>();

//now we can retrieve individual records using the ID's retrieved above
// foreach (int i in distinctLatest)
// {
//    var res = from g in ee.Records where g.id == i select g;
//    var arr = res.ToArray();
//    result.Add(res.First());
// }

// alternate version of foreach
dgvLatestDistinctRec.DataSource = from g in ee.Records
                                           join i in distinctLatest
                                           on g.id equals i
                                           select g;

I had another idea:

// Get a list of all the id's i need by:
// grouping by CustID, and then selecting Max ID from each group.
var distinctLatest = (from x in ee.Records
                          group x by x.CustID into grp 
                          select grp.Max(g => g.id)).ToArray();

// List<Record> result = new List<Record>();

//now we can retrieve individual records using the ID's retrieved above
// foreach (int i in distinctLatest)
// {
//    var res = from g in ee.Records where g.id == i select g;
//    var arr = res.ToArray();
//    result.Add(res.First());
// }

// alternate version of foreach
dgvLatestDistinctRec.DataSource = from g in ee.Records
                                           join i in distinctLatest
                                           on g.id equals i
                                           select g;
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文