如何在 Linq Query 中应用自连接?

How to apply self join in Linq Query?

书籍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 查询,它将 return 我的行对应于每个 gold if sil 供应商编号不存在。 vendor Id 的最后三位数字是该行中对应的 ASIN 列。

Ex- 对于 gold123 对应的 sil123 存在,因此行不会被 returned 但对于 gold678 和 gold980 对应的 sil 不存在。所以这些行将被 returned.

我尝试关注

     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));

我们能否应用自连接或更好的方法来仅在一个查询中获得结果,而不是两个查询和其他几个列表语句。

看看是否有帮助 -

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();

我所做的是-

  • 已选择具有匹配 ASIN 的记录
  • 按 VendorID 对它们进行分组
  • 没有sil
  • 的精选

这只是另一个谓词,"where a corresponding silver vendor doesn't exist":

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();

在许多情况下,这是一个成功的秘诀:使用您想要 return 的实体开始查询,并且只添加谓词。一般来说,连接不应该用于过滤,而只能用于收集相关数据,尽管在这种情况下应该使用导航属性,它隐式转换为 SQL 连接。