我仍然在理解LINQ。下面是我想要转换的SQL。我想要那些Max Seq等于同类的独特身份。
SELECT es.Ident
FROM EqpSeq es
INNER JOIN EqpSeq esMax on esMax.Ident= es.Ident
WHERE es.Class = 4
GROUP BY es.Ident, es.Seq
HAVING es.Seq= Max(esMax.Seq);
数据看起来像
Ident Seq Class
10 1 4
10 2 5
10 3 4
Class = 4时的结果应为
Ident
10
Class = 5时的结果应为null。
我认为这个LINQ查询可能有效,但它返回两行Ident 10。
from es in EqpSeqs
join esMax in EqpSeqs on es.Ident equals esMax.Ident
where es.Class == 4
group es by new {
es.Ident, es.Seq
} into g
where g.Key.Seq == g.Max(p => p.Seq)
select new {
Ident = (int?)g.Key.Ident
}
任何想法都将不胜感激。我很想看到LINQ流畅的风格。
答案 0 :(得分:0)
是的,根据您的样本数据,两次获得相同的值并不奇怪。您正在Ident
上将表格连接到自身,但Ident
的值在每一行中都相同。连接的结果基本上是行的笛卡尔积:
es.Ident es.Seq es.Class esMax.Ident esMax.Seq esMax.Class
10 1 4 10 1 4
10 1 4 10 2 5
10 1 4 10 3 4
10 2 5 10 1 4
10 2 5 10 2 5
10 2 5 10 3 4
10 3 4 10 1 4 // This row matches
10 3 4 10 2 5
10 3 4 10 3 4 // So does this row
正如所建议的,在查询中添加Distinct
应解决此问题:
(from es in EqpSeqs
join esMax in EqpSeqs on es.Ident equals esMax.Ident
where es.Class == 4
group es by new {
es.Ident, es.Seq
} into g
where g.Key.Seq == g.Max(p => p.Seq)
select new {
Ident = (int?)g.Key.Ident
})
.Distinct();
您也可以尝试几种不同的查询。
我经常使用Ix-Main
NuGet包。该软件包附带了非常方便的MaxBy
功能。如果你不介意添加该软件包,你可以这样做:
EqpSeq
.GroupBy(x => new { x.Ident, x.Seq })
.MaxBy(x => x.Key.Seq)
.SelectMany(x => x)
.Where(x => x.Class == 4)
.Select(x => x.Ident)
.Distinct();
你可以在没有Ix-Main
的情况下做同样的事情:
EqpSeq
.Where(x => x.Seq == EqpSeq.Max(y => y.Seq) && x.Class == 4)
.Select(x => x.Ident)
.Distinct();
在我的头脑中,我不确定三个查询中哪一个最高效。如果Seq
列被编入索引,那么我的赌注是第三个查询可能是赢家。
答案 1 :(得分:0)
谢谢大家的回复。我今天早上坐下来上班前大声说出我想要的东西,想出了以下内容,不确定这是否最有效:
SELECT es.EqpIdentID
FROM EqpSeq es
WHERE es.EqpClassID = 4 and
es.Seq = (SELECT Max(Seq) FROM EqpSeq esMax WHERE esMax.EqpIdentID = es.EqpIdentID)
Linqer制作的相应LINQ是:
from es in db.EqpSeqs
where
es.EqpClassID == 4 &&
es.Seq ==
(from esMax in db.EqpSeqs
where
esMax.EqpIdentID == es.EqpIdentID
select new {
esMax.Seq
}).Max(p => p.Seq)
select new {
es.EqpIdentID
}
LINQ Fluent / Method语法为:
EqpSeqs
.Where(es => es.EqpClassID == 4 &&
es.Seq == EqpSeqs
.Where(esMax => esMax.EqpIdentID == es.EqpIdentID).Max(a => a.Seq))
.Select(b => b.EqpIdentID)