LINQ到SQL - 左外连接有多个连接条件
我有以下SQL,这我想转换为LINQ:LINQ到SQL - 左外连接有多个连接条件
SELECT f.value
FROM period as p
LEFT OUTER JOIN facts AS f ON p.id = f.periodid AND f.otherid = 17
WHERE p.companyid = 100
我见过的左外的典型实现连接(即。 into x from y in x.DefaultIfEmpty()
等),但我不能确定如何引入其他的连接条件(AND f.otherid = 17
)
编辑
为什么的AND f.otherid = 17
条件的一部分JOIN而不是在WHERE子句中? 因为f
可能不存在的一些行,我仍然希望这些行被包括在内。如果条件在WHERE子句中应用,在JOIN之后 - 那么我没有得到我想要的行为。
不幸的:
from p in context.Periods
join f in context.Facts on p.id equals f.periodid into fg
from fgi in fg.DefaultIfEmpty()
where p.companyid == 100 && fgi.otherid == 17
select f.value
似乎是相同的:
SELECT f.value
FROM period as p
LEFT OUTER JOIN facts AS f ON p.id = f.periodid
WHERE p.companyid = 100 AND f.otherid = 17
这是不太我后。
在致电DefaultIfEmpty()
之前,您需要先介绍您的加入条件。我只想用扩展方法的语法:
from p in context.Periods
join f in context.Facts on p.id equals f.periodid into fg
from fgi in fg.Where(f => f.otherid == 17).DefaultIfEmpty()
where p.companyid == 100
select f.value
或者你可以使用子查询:
from p in context.Periods
join f in context.Facts on p.id equals f.periodid into fg
from fgi in (from f in fg
where f.otherid == 17
select f).DefaultIfEmpty()
where p.companyid == 100
select f.value
另一个有效方法是地摊加入跨多个LINQ条款,具体如下:
public static IEnumerable<Announcementboard> GetSiteContent(string pageName, DateTime date)
{
IEnumerable<Announcementboard> content = null;
IEnumerable<Announcementboard> addMoreContent = null;
try
{
content = from c in DB.Announcementboards
//Can be displayed beginning on this date
where c.Displayondate > date.AddDays(-1)
//Doesn't Expire or Expires at future date
&& (c.Displaythrudate == null || c.Displaythrudate > date)
//Content is NOT draft, and IS published
&& c.Isdraft == "N" && c.Publishedon != null
orderby c.Sortorder ascending, c.Heading ascending
select c;
//Get the content specific to page names
if (!string.IsNullOrEmpty(pageName))
{
addMoreContent = from c in content
join p in DB.Announceonpages on c.Announcementid equals p.Announcementid
join s in DB.Apppagenames on p.Apppagenameid equals s.Apppagenameid
where s.Apppageref.ToLower() == pageName.ToLower()
select c;
}
//CROSS-JOIN this content
content = content.Union(addMoreContent);
//Exclude dupes - effectively OUTER JOIN
content = content.Distinct();
return content;
}
catch (MyLovelyException ex)
{
throw ex;
}
}
不会比在单个linq查询中执行整个操作慢? – 2017-06-23 11:16:11
@ umar-t,很可能,考虑到这是八年多前我写的。我个人喜欢Dahlbyk推荐的相关子查询https://*.com/a/1123051/212950 – MAbraham1 2017-06-23 17:11:55
这个工作太...如果你有多个列连接
from p in context.Periods
join f in context.Facts
on new {
id = p.periodid,
p.otherid
} equals new {
f.id,
f.otherid
} into fg
from fgi in fg.DefaultIfEmpty()
where p.companyid == 100
select f.value
在尝试翻译它之前,我认为在考虑对SQL代码进行一些重写时有价值。
就个人而言,我会写这样的查询作为工会(虽然我完全避免空!):
SELECT f.value
FROM period as p JOIN facts AS f ON p.id = f.periodid
WHERE p.companyid = 100
AND f.otherid = 17
UNION
SELECT NULL AS value
FROM period as p
WHERE p.companyid = 100
AND NOT EXISTS (
SELECT *
FROM facts AS f
WHERE p.id = f.periodid
AND f.otherid = 17
);
所以我想我同意@ MAbraham1的答案的精神(虽然他们的代码似乎与这个问题无关)。
但是,它似乎查询是明确设计的产生包含重复行的单列结果 - 的确是重复的空值!很难不会得出这种方法存在缺陷的结论。
我知道这是“有点晚”,但如何做到这一点只是如果有人需要为此在LINQ方法语法(这就是为什么我发现这个职位最初)的情况下,这将是:
var results = context.Periods
.GroupJoin(
context.Facts,
period => period.id,
fk => fk.periodid,
(period, fact) => fact.Where(f => f.otherid == 17)
.Select(fact.Value)
.DefaultIfEmpty()
)
.Where(period.companyid==100)
.SelectMany(fact=>fact).ToList();
甜!我一直在寻找这一段时间,但不知道如何搜索这个。不知道如何添加标签到这个答案。这里是我使用的搜索条件: LINQ到SQL过滤器在连接或从 LINQ到SQL where子句在连接或从 – Solburn 2010-09-21 14:59:01