SQL->;LINQ(C#)
我有一个SQL查询(如下所示),它从tbStudents中获取一个student,然后获取tbTerms中最新的术语(一个数字,但存储为字符串) 在tbTerms中,学生与学生之间存在一对多的关系,在tbTerms中,学生与学期记录之间存在一对多的关系。例如: 学生:SQL->;LINQ(C#),c#,sql,linq,C#,Sql,Linq,我有一个SQL查询(如下所示),它从tbStudents中获取一个student,然后获取tbTerms中最新的术语(一个数字,但存储为字符串) 在tbTerms中,学生与学生之间存在一对多的关系,在tbTerms中,学生与学期记录之间存在一对多的关系。例如: 学生: StudentId FirstName LastName 12345 John Smith 12346 Jane Doe 技术条款: StudentId Term 12345 1234
StudentId FirstName LastName
12345 John Smith
12346 Jane Doe
技术条款:
StudentId Term
12345 1234
12345 1235
12345 1236
12346 1233
12346 1234
期望的:
StudentId FirstName LastName Term
12345 John Smith 1236
12346 Jane Doe 1234
SQL查询:
select tbStudents.student_id, tbStudents.user_id, tbStudents.firstname, tbStudents.lastname, v.rTerm
from tbStudents
inner join (
select tbTerms.student_id, MAX(tbTerms.term) as rTerm
from tbTerms
group by tbTerms.student_id
) v on v.student_id = tbStudents.student_id
我一直试图把这一切都写进一个LINQ声明中,但我遇到了麻烦。在一份声明中是否有这样做的必要?或者必须在多个语句中完成。提前谢谢
编辑:我尝试过的代码
var students = (from s in dockDb.tbStudents
join t in dockDb.tbTerms on s.student_id equals t.student_id
into pairs
from p in pairs
select new { UserId = s.user_id, StudentId = s.student_id, Term = p.term } ).ToList();
输出类似于:
StudentId FirstName LastName Term
12345 John Smith 1234
12345 John Smith 1235
12345 John Smith 1236
12346 Jane Doe 1233
12346 Jane Doe 1234
编辑#2:我正在对数据使用实体框架。我不确定这是否会影响什么,但当我尝试这些解决方案时,大多数解决方案都是“语法错误的”。您应该尝试类似的方法:
from s in dockDb.tbStudents
join t in dockDb.tbTerms on t.student_id equals s.student_id into st
group st by New {StudentID = st.student_id, Term = t.term} into g
select New { g.Key, g.Max(i => i.Term) }
不知何故,我一直认为扩展方法的语法更具可读性和自然性。下面是:
context.Students.Select(s => new
{
s.StudentId,
s.FirstName,
s.LastName,
Term = context.Terms.Where(t => t.StudentId == s.StudentId)
.Select(t => t.TermNumber)
.OrderByDescending(t => t)
.First()
});
基本上,对于每个学生,它选择他/她的所有术语,从最近到最不最近排序,并在结果中包括第一个(最近的)。应该是可能的。试试这个:
from s in Students
join t in Terms on t.StudentId = s.StudentId
select new {Student = s, Term = t}
group by s into g
select new {g.Key.StudentId, g.Key.FirstName, g.Key.LastName, g.Max(x=>x.Term.term)};
将其分解,前两行定义要搜索的域;即学生与词汇的内在联结组合,由学生ID联结。Student和Term的每个唯一组合都被放入一个匿名类型中,然后这些实例由每个唯一的Student分组到一个查找中(键引用的IEnumerables的只读集合)。在中,我们可以选择关键的(学生的)重要信息,并在术语列表中找到具有最高值的(将是最新的)。是您的朋友。让我们简单地按学生id将数据分组,然后将其投影到一个新表单。这是一个linqpad示例:
void Main()
{
var students = new List<Student>()
{
new Student() { StudentID = 12345, Name = "Smith" },
new Student() { StudentID = 12346, Name = "Jones" }
};
var terms = new List<Term>()
{
new Term() { StudentID=12345, TermID = 1234 },
new Term() { StudentID=12345, TermID = 1235 },
new Term() { StudentID=12345, TermID = 1236 },
new Term() { StudentID=12345, TermID = 1237 },
new Term() { StudentID=12346, TermID = 1233 },
new Term() { StudentID=12346, TermID = 1234 },
};
var result = terms.GroupBy (tm => tm.StudentID)
.Select (gr => new
{
Name = students.First (s => s.StudentID == gr.Key).Name,
Terms = gr.Select (g => g.TermID)
});
result.Dump();
}
// Define other methods and classes here
public class Student
{
public int StudentID { get; set; }
public string Name { get; set; }
}
public class Term
{
public int StudentID { get; set; }
public int TermID { get; set; }
}
void Main()
{
var students=新列表()
{
new Student(){StudentID=12345,Name=“Smith”},
new Student(){StudentID=12346,Name=“Jones”}
};
var terms=新列表()
{
新术语(){StudentID=12345,TermID=1234},
新术语(){StudentID=12345,TermID=1235},
新术语(){StudentID=12345,TermID=1236},
新术语(){StudentID=12345,TermID=1237},
新术语(){StudentID=12346,TermID=1233},
新术语(){StudentID=12346,TermID=1234},
};
var result=terms.GroupBy(tm=>tm.StudentID)
.选择(gr=>new
{
Name=students.First(s=>s.StudentID==gr.Key).Name,
术语=组选择(g=>g.TermID)
});
result.Dump();
}
//在此处定义其他方法和类
公立班学生
{
公共int StudentID{get;set;}
公共字符串名称{get;set;}
}
公共类术语
{
公共int StudentID{get;set;}
公共int TermID{get;set;}
}
以下是可以使用的输出:
你能展示你已经拥有的吗?“语法错误”。调用扩展名AsEnumerable()。我不得不修改代码中的一些内容使其运行,但除此之外,您的结构正是我所需要的。谢谢