Books Table
Id VendorId ASIN Price
-- -------- ---- ------
1 gold123 123 10
2 sil123 123 11
3 gold456 456 15
4 gold678 678 12
5 sil456 456 12
6 gold980 980 12
我想编写一个linq查询,如果 sil 供应商ID不存在,它将返回与每个黄金相对应的行。供应商ID的后三位是该行中相应的ASIN列。
Ex-对于gold123,对应的sil123存在,因此不会返回行,但是对于gold678和gold980,对应的sil不存在。因此这些行将被返回。
我尝试关注
var gold = _repository.Query<Books>().Where(x =>
x.VendorId.Contains("gold"))
.OrderBy(x => x.Id).Skip(0).Take(500).ToList();
var asinsForGold = gold.Select(x => x.ASIN).ToList();
var correspondingSilver = _repository.Query<Books>().Where(x =>
x.VendorId.Contains("sil")
&& asinsForGold.Contains(x.ASIN)).ToList();
var correspondingSilverAsins = correspondingSilver.Select(x => x.ASIN).ToList();
var goldWithoutCorrespondingSilver = gold.Where(x =>
!correspondingSilverAsins.Contains(x.ASIN));
我们可以采用自联接还是更好的方法仅在一个查询中而不是两个查询和其他几个列表语句中获得结果。
答案 0 :(得分:2)
这只是另一个谓词,“不存在相应的白银供应商”:
var goldWoSilver = _repository.Query<Books>()
.Where(x => x.VendorId.Contains("gold"))
.Where(x => !_repository.Query<Books>()
.Any(s => s.ASIN == x.ASIN
&& s.VendorId.Contains("sil"))
.OrderBy(x => x.Id).Skip(0).Take(500).ToList();
在许多情况下,这是成功的秘诀:从您要返回的实体开始查询,仅添加谓词。通常,不应将联接用于过滤,而只能用于收集相关数据,尽管在这种情况下,应使用导航属性来隐式转换为SQL联接。
答案 1 :(得分:0)
看看是否有帮助-
var goldWithoutCorrespondingSilver = from b1 in books
join b2 in books on b1.ASIN equals b2.ASIN
where b1.VendorId.Contains("gold")
group b2 by b1.VendorId into g
where !g.Any(x => x.VendorId.Contains("sil"))
select g.FirstOrDefault();
我所做的是-