如何计算Linq左连接右侧没有匹配的记录数?

时间:2016-01-13 12:36:01

标签: c# linq left-join

我正在尝试分析一个电话帐单,其中包含一大堆手机号码和相关数据。每个号码都属于公司中的某个人,或者是未分配的。

我正在使用此查询将手机号码与员工记录相匹配

var billInfo = from  row in csvTable.AsEnumerable()
               join d in employeeList 
               on row.Field<string>("Phone number") equals d.Mobile into t 
                from rt in t.DefaultIfEmpty()
                    select new
                     {
                       empNo = rt == null ? null : rt.EmpNo,
                       totalRows = csvTable.Rows.Count,
                       unassignedNumbers = t.Where(x => x.EmpNo == null).Count(),
                       name = row.Field<string>("User name"),
                       mobile = row.Field<string>("Phone number")
                      };

我想在unassignedNumbers字段中返回未分配的数字。 (即如果csvTable数据表中有100行(每个电话号码一个),并且70个员工记录在employeeList中匹配,我想返回30作为值 - 没有匹配员工的行数。)

以下一行:

unassignedNumbers = t.Where(x => x.EmpNo == null).Count,

是问题所在。它总是评估为零,而不是具有“空”员工编号(empNo)的行数。

2 个答案:

答案 0 :(得分:4)

使用Count(),而不是Count。后者是ICollection<T>属性,而您正在处理IEnumerable<T>

至于查询的逻辑,您在t.Where()上运行t,这是一个内部联接。尝试

var billInfo = (from  row in csvTable.AsEnumerable()
           join d in employeeList 
           on row.Field<string>("Phone number") equals d.Mobile into t 
           from rt in t.DefaultIfEmpty()
           where rt == null
           select row.Field<string>("Phone number")).Count();

答案 1 :(得分:1)

您的查询为csvTable中的每个项目至少提供了一项。您想要的unassignedNumbers数据只是整个数据集的一个值。因此,您必须执行完全独立的查询才能执行此操作,然后根据需要将该值直接分配到查询结果中。

int allUnassignedNumbers = 
    (from  row in csvTable.AsEnumerable()
    join d in employeeList 
    on row.Field<string>("Phone number") equals d.Mobile into t 
    from rt in t.DefaultIfEmpty()
    where rt == null
    select 1).Count();

var billInfo = 
    from  row in csvTable.AsEnumerable()
    join d in employeeList 
    on row.Field<string>("Phone number") equals d.Mobile into t 
    from rt in t.DefaultIfEmpty()
    select new
    {
        empNo = rt == null ? null : rt.EmpNo,
        totalRows = csvTable.Rows.Count,
        unassignedNumbers = allUnassignedNumbers,
        name = row.Field<string>("User name"),
        mobile = row.Field<string>("Phone number")
    };