LINQ select 不同的设置和检索不同的列
LINQ select distinct set and retrive different column
我希望能够执行以下查询:
select distinct studentname, subject, grade from studenttable;
学生 table 有以下字段:
studentid
studentname
subject
grade
我现在的linq查询是:
var students=dc.Select(s => new {s.studentname, s.subject, s.grade}).Distinct();
dc 是数据上下文。
此查询有效,但如何在满足 studentname, subject, grade
集合上的不同条件的同时获取学生 id
?
这里的问题是您已经收集了必要数据的三个属性,虽然它们足以通过 Distinct
,但没有任何 link 返回到它们的原始数据,任何这样的 link 都会破坏 Distinct
.
的默认实现
但是,您可以做的是使用 distinct which takes an IEqualityComparer 的重载。这将允许您只比较所需字段的相等性,而 运行 在整个集合中不同。
var students = dc
.AsEnumerable() // In case you're using a linq-to-sql framework, this will ensure the query execute in-memory
.Distinct(new SpecialtyComparer());
//...
public class SpecialtyComparer : IEqualityComparer<StudentTable>
{
public int GetHashCode(StudentTable s)
{
return s.studentname.GetHashCode()
&& s.subject.GetHashCode()
&& s.grade.GetHashCode();
}
public bool Equals(StudentTable s1, StudenTable s2)
{
return s1.studentname.Equals(s2.studentname)
&& s1.subject.Equals(s2.subject)
&& s1.grade.Equals(s2.grade);
}
}
在对象列表上执行 Distinct()
时,您会将这些行聚合成较少的行,并丢弃任何重复项。因此,您的结果将不再有 studentid
。要保留 studentid
属性,您需要使用 GroupBy
。这将为您 return 您的密钥(studentname
、subject
、grade
的学生)和原始行列表。您可以在此处查看此问题中的示例:(GroupBy and count the unique elements in a List).
您将有一个 studentids
列表可供选择,因为可能有许多行具有相同的 studentname
、subject
和 grade
。 (否则你不会做不同的——它们将是唯一的,tuple { sudentname, subject, grade }
将是一个 自然键 )。所以你可能需要问自己的问题是 "Which studentid do I need?"
我认为你的设计有问题,但我会回答你的具体问题....
我假设您正在尝试按姓名、学科和年级分组,并检索每组的第一个代表学生。
在这种情况下,您可以按元组分组。一个元组会免费给你一个 Equals
和 GetHashCode
方法,所以可以在组操作中使用。
IEnumerable<Student> distinctStudents = students
.AsEnumerable()
.GroupBy(s => Tuple.Create
(
s.studentname,
s.subject,
s.grade
)
)
.Select(g => g.First()); /// Returns the first student of each group
这是一个点网 fiddle 示例:https://dotnetfiddle.net/7K13DJ
我希望能够执行以下查询:
select distinct studentname, subject, grade from studenttable;
学生 table 有以下字段:
studentid
studentname
subject
grade
我现在的linq查询是:
var students=dc.Select(s => new {s.studentname, s.subject, s.grade}).Distinct();
dc 是数据上下文。
此查询有效,但如何在满足 studentname, subject, grade
集合上的不同条件的同时获取学生 id
?
这里的问题是您已经收集了必要数据的三个属性,虽然它们足以通过 Distinct
,但没有任何 link 返回到它们的原始数据,任何这样的 link 都会破坏 Distinct
.
但是,您可以做的是使用 distinct which takes an IEqualityComparer 的重载。这将允许您只比较所需字段的相等性,而 运行 在整个集合中不同。
var students = dc
.AsEnumerable() // In case you're using a linq-to-sql framework, this will ensure the query execute in-memory
.Distinct(new SpecialtyComparer());
//...
public class SpecialtyComparer : IEqualityComparer<StudentTable>
{
public int GetHashCode(StudentTable s)
{
return s.studentname.GetHashCode()
&& s.subject.GetHashCode()
&& s.grade.GetHashCode();
}
public bool Equals(StudentTable s1, StudenTable s2)
{
return s1.studentname.Equals(s2.studentname)
&& s1.subject.Equals(s2.subject)
&& s1.grade.Equals(s2.grade);
}
}
在对象列表上执行 Distinct()
时,您会将这些行聚合成较少的行,并丢弃任何重复项。因此,您的结果将不再有 studentid
。要保留 studentid
属性,您需要使用 GroupBy
。这将为您 return 您的密钥(studentname
、subject
、grade
的学生)和原始行列表。您可以在此处查看此问题中的示例:(GroupBy and count the unique elements in a List).
您将有一个 studentids
列表可供选择,因为可能有许多行具有相同的 studentname
、subject
和 grade
。 (否则你不会做不同的——它们将是唯一的,tuple { sudentname, subject, grade }
将是一个 自然键 )。所以你可能需要问自己的问题是 "Which studentid do I need?"
我认为你的设计有问题,但我会回答你的具体问题....
我假设您正在尝试按姓名、学科和年级分组,并检索每组的第一个代表学生。
在这种情况下,您可以按元组分组。一个元组会免费给你一个 Equals
和 GetHashCode
方法,所以可以在组操作中使用。
IEnumerable<Student> distinctStudents = students
.AsEnumerable()
.GroupBy(s => Tuple.Create
(
s.studentname,
s.subject,
s.grade
)
)
.Select(g => g.First()); /// Returns the first student of each group
这是一个点网 fiddle 示例:https://dotnetfiddle.net/7K13DJ