【问题标题】:Left outer join to include null values linq lambda左外连接以包含空值 linq lambda
【发布时间】:2022-01-13 07:43:16
【问题描述】:

我在数据库中有一个名为 Balance 的表和一个日期列表,如下所示:

List<string> allDates = { "2021-01-02", "2021-01-03", "2021-01-04" }

余额表:

Id, Amount, BalanceDate
1, 233, "2021-01-02"
2, 442, "2021-01-03

我需要获取余额表中缺失日期的金额为 0 的记录。例如:

233, "2021-01-02"
442, "2021-01-03"
0, "2021-01-04"

我尝试了以下方法:

balnces.GroupJoin(allDates,
       balance => balance.Date,
       d => d,
       (balance, d) => balance);

但是记录还是一样的(只有余额表中的)

【问题讨论】:

  • 您可以发布任何自己的尝试吗?您遇到的任何问题描述?是数据库中的余额表吗?
  • 数据库部分非常重要,因为你cannot simply join a table with a list
  • @MongZhu 我已经添加了我的尝试。余额表就是上面提到的数据库表
  • 请始终提及您使用的数据访问类型,例如实体框架 + 哪个版本。使用标签来表明这一点。也就是说,GroupJoin 等价于 left 外连接。这里的左边是天平。如果您想查看所有日期,日期应在左侧。

标签: c# asp.net linq lambda left-join


【解决方案1】:

给定数据库中的数据结构:

        private class balance
    {
        public int id { get; set; }
        public double amount { get; set; }
        public string date { get; set; }
    }

您可以根据需要获取数据(这只是一个模型)

       List<string> allDates = new List<string> { "2021-01-02", "2021-01-03", "2021-01-04" };
        List<balance> balances = new List<balance>();
        balances.Add(new balance { id = 1, amount = 233 , date = "2021-01-02" });
        balances.Add(new balance { id = 2, amount = 442, date = "2021-01-03" });

你可以通过这种方式得到你想要的结果:

        List<balance> result = allDates.Select(d=> 
            new balance { 
                amount = 
                  balances.Any(s=> s.date == d)?
                         balances.FirstOrDefault(s => s.date == d).amount:0,
                date = d
        }).ToList();

如果您的默认值包含 0 而不是 null,则可以跳过 .Any 检查

【讨论】:

    【解决方案2】:

    假设

    余额查询已具体化,数据已从数据库返回。

    解决方案 1:使用.DefaultIfEmpty()

    using System.Linq;
    
    var result = (from a in allDates
                join b in balances on a equals b.Date.ToString("yyyy-MM-dd") into ab
                from b in ab.DefaultIfEmpty()
                select new { Date = a, Amount = b != null ? b.Amount : 0 }
                ).ToList();
    

    Sample Program for Solution 1


    解决方案 2:使用.ToLookup()

    var lookup = balances.ToLookup(x => x.Date.ToString("yyyy-MM-dd"));
    
    var result = (from a in allDates
                select new 
                { 
                    Date = a, 
                    Amount = lookup[a] != null && lookup[a].Count() > 0 ? lookup[a].First().Amount : 0
                }
                ).ToList();
    

    Sample Program for Solution 2

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-01-22
      • 1970-01-01
      • 2011-08-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多