我有两个表学生和标记。
学生包含以下字段:
StudentID
,Name
,MarkID(Nullable)
。
标记包含以下字段:
MarkID
,Mark
学生表
StudentID Name MarkID
1 Mark 1
2 Mike NULL
3 John NULL
4 Paul 2
标记表
MarkID Mark
1 80
2 100
我只使用左连接方式mark
和paul
记录。
我想要左表中的所有记录(Student
)
我的查询是:
var query=(from s in Students join m in Marks on s.MarkID equals m.MarkID into mar
from subMark in mar.DefaultIfEmpty()
Select s.Name).ToList()
注意:这只是一个示例 如果包含NULL值的Left表示当时左连接没有带来该记录,则使用左连接连接两个表。 请帮助我。
答案 0 :(得分:4)
NULL比较始终 false。这就是SQL的三值逻辑的工作方式。如果要匹配值均为null的行,则应使用将它们都检查为null的语句。
在SQL语句中,您可以写:
ON S.MARKID=M.MARKID OR (S.MARKID IS NULL AND M.MARKID IS NULL)
在C#中,您可以使用比较运算符,LINQ提供程序会将其转换为IS NULL
,例如:
on s.MarkID == m.MarkID || (s.MarkID == null && m.MarkID==null)
答案 1 :(得分:2)
/编辑:我的第一个答案是使用FULL OUTER JOIN。这是超越顶部的方式,可能是错误的,或者不是完全正确的。
新答案使用LEFT OUTER JOIN。我使用LinqPad创建了一些示例数据,以获得一个工作示例。如果您不使用LinqPad,请忽略.Dump()
方法。
var Students = new List<Student>() {
new Student() {StudentId = 1, Name ="John", MarkId = 1},
new Student() {StudentId = 1, Name ="Paul", MarkId = 1},
new Student() {StudentId = 1, Name ="Steve", MarkId = 1},
new Student() {StudentId = 1, Name ="John", MarkId = 2},
new Student() {StudentId = 1, Name ="Paul", MarkId = 3},
new Student() {StudentId = 1, Name ="Steve", MarkId = 1},
new Student() {StudentId = 1, Name ="Paul", MarkId = 3},
new Student() {StudentId = 1, Name ="John" },
new Student() {StudentId = 1, Name ="Steve" },
new Student() {StudentId = 1, Name ="John", MarkId = 1}
};
var Marks = new List<Mark>() {
new Mark() {MarkId = 1, Value = 60},
new Mark() {MarkId = 2, Value = 80},
new Mark() {MarkId = 3, Value = 100}
};
var StudentMarks = Students
.GroupJoin(
Marks,
st => st.MarkId,
mk => mk.MarkId,
(x,y) => new {
StudentId = x.StudentId,
Name = x.Name,
Mark = y.Select (z => z.Value).SingleOrDefault()
}
)
.Dump();
}
public class Student
{
public int StudentId { get; set; }
public string Name { get; set; }
public int MarkId { get; set; }
}
public class Mark
{
public int MarkId { get; set; }
public int Value { get; set; }
}
输出:
正如你在我的学生名单中看到的那样,有一个没有MarkId的2名学生。这些2获得由.SingleOrDefault()
分配的默认值。我认为这将解决您的问题,并为您提供进一步填补的良好基础。
的引用: How do you perform a left outer join using linq extension methods
答案 2 :(得分:2)
问题是我们在Left join中使用where子句。因此它将丢弃空值记录。
var sampleQuery= (from f in food
join j in juice on f.ID equals j.ID into juiceDetails from juice in juiceDetails.DefaultIfEmpty()
where(!j.deleted)
join fr in fruit on f.ID equals fr.ID into fruitDetails from fruit in fruitDetails.DefaultIfEmpty()
where(!fr.deleted)
select new
{
// codes
});
而不是这个,我们必须检查表本身的where子句。就像这个
var sampleQuery= (from f in food
join j in juice.Table().where(x=>!x.deleted) on f.ID equals j.ID into juiceDetails from juice in juiceDetails.DefaultIfEmpty()
join fr in fruit.Table().where(x=>!x.deleted) on f.ID equals fr.ID into fruitDetails from fruit in fruitDetails.DefaultIfEmpty()
select new
{
// codes
});
它会正常工作。 谢谢。
答案 3 :(得分:1)
在您的查询中,您在加入时在Join语句中编写了From
。
相反,您应该使用in
::
from s in Students
join m in Marks on s.MarkID equals m.ID into mar
from subMark in mar.DefaultIfEmpty()
Select s.Name).ToList()
答案 4 :(得分:0)
我有同样的问题。仅当subMark中至少有一行时,此解决方案才有效。行的ID无关紧要。
var query = (from s in Students
join m in Marks on s.MarkID equals m.MarkID into fullM
into mar from subMark in mar.DefaultIfEmpty()
where(m.Mark > 80)
Select s.Name)
.ToList()
将关键字 into 变成魔术。添加该行会显示所有行以及3月中具有NULL值的行。