用linq减去两个表

时间:2017-04-11 20:12:42

标签: c# asp.net linq

这是我的第一篇文章,希望你能帮助我。我没有找到答案,所以我在这里:

我在SQL中创建了这个查询并且它有效。

string consultaSQL =
                    @"SELECT a.GastosEstudio - ISNULL(SUM(b.GastosEstudioR),0) AS restagastos, a.Articulo - ISNULL(SUM(b.ArticuloR),0) AS restaarticulo, a.Honorarios - ISNULL(SUM(b.HonorariosR),0) AS restahonorarios, a.IVAHonorarios - ISNULL(SUM(b.IVAHonorariosR),0) AS restaivahonorarios FROM deudores a LEFT JOIN recibos b ON a.DNI=b.DNI WHERE a.DNI = @DNI GROUP BY a.GastosEstudio, a.Articulo, a.Honorarios, a.IVAHonorarios";

现在我需要在LINQ中做同样的事情。基本上:我有两个表(deudoresrecibos)。在deudores我有不同概念(列)的债务:

gastos, articulo, honorarios, ivahonorarios

在表recibos中,我插入了具有相同列的收据。

SQL查询对收据进行求和并减去债务。我在LINQ中最接近的是:

var query = (from d in bd.deudores                         
             join r in bd.recibos on d.DNI equals r.DNI
             where d.DNI == DNI
             group d by d.DNI into g
             select new
                     {
                         DNI = g.Key,
                         articulo = g.Max(x => x.Articulo) - g.Sum(x => x.ArticuloR),
                         gastos = g.Max(x => x.GastosEstudio) - g.Sum(x => x.GastosEstudioR),
                         honorarios = g.Max(x => x.Honorarios) - g.Sum(x => x.HonorariosR),
                         ivah = g.Max(x => x.IVAHonorarios) - g.Sum(x => x.IVAHonorariosR),
                     });

此查询的问题在于,如果没有收据,则不显示任何信息(应显示初始债务)

我尝试DefaultIfEmpty,但没有工作:

var query = (from d in bd.deudores
             join r in bd.recibos on d.DNI equals r.DNI into Pagos
             from p in Pagos.DefaultIfEmpty()
             where d.DNI == DNI
             group d by d.DNI into g
             select new
 {
     DNI = g.Key,
     articulo = g.Max(x => x.Articulo) - g.SelectMany(x => x.recibos).Count() >= 1
        ? g.SelectMany(x => x.recibos).Sum(y => y.ArticuloR)
        : 0,
     gastos = g.Max(x => x.GastosEstudio) - g.SelectMany(x => x.recibos).Count() >= 1
            ? g.SelectMany(x => x.recibos).Sum(y => y.GastosEstudioR)
        : 0,
     honorarios = g.Max(x => x.Honorarios) - g.SelectMany(x => x.recibos).Count() >= 1
        ? g.SelectMany(x => x.recibos).Sum(y => y.HonorariosR)
        : 0,
     ivah = g.Max(x => x.IVAHonorarios) - g.SelectMany(x => x.recibos).Count() >= 1
        ? g.SelectMany(x => x.recibos).Sum(y => y.IVAHonorariosR)
        : 0
 });

此查询的问题在于它不会减去它。

有什么建议吗?

谢谢!

2 个答案:

答案 0 :(得分:1)

您希望等效于外部联接,因此您可以正确转向GroupJoin, or join ... into。但查询部分......

 from d in bd.deudores
 join r in bd.recibos on d.DNI equals r.DNI into Pagos
 from p in Pagos.DefaultIfEmpty()
 where d.DNI == DNI
 group d by d.DNI into g

......比你想做的更多。在流畅的LINQ语法中,其结构等同于

bd.deudores.GroupJoin(bd.recibos, ...)
           .SelectMany(...)
           .GroupBy(...)

关键是第一个GroupJoin会创建一个deudores的集合,每个集合都有一个recibos组,可能是空的。然后,SelectMany将其展平为一对deudores和一个recibos 或null 。随后,GroupBy会创建包含null元素的组。

第一个GroupJoin就是您所需要的:

from d in bd.deudores
join r in bd.recibos on d.DNI equals r.DNI into g
select new
{
    DNI = d.DNI,
    articulo = d.Articulo - g.Select(x => x.ArticuloR).DefaultIfEmpty().Sum(),
    gastos = d.GastosEstudio - g.Select(x => x.GastosEstudioR).DefaultIfEmpty().Sum(),
    honorarios = d.Honorarios - g.Select(x => x.HonorariosR).DefaultIfEmpty().Sum(),
    ivah = d.IVAHonorarios - g.Select(x => x.IVAHonorariosR).DefaultIfEmpty().Sum()
});

通过添加DefaultIfEmpty(),确保Sum在没有元素时返回0。

答案 1 :(得分:0)

@Gert Arnold:两个表之间的关系是列名DNI。在表deudores中是PK,表recibos中是FK。昨晚我尝试了这段代码并且有效:

var query = (from d in bd.deudores 
         join r in bd.recibos 
         on d.DNI equals r.DNI into g
         where d.DNI == DNI 
         select new 
         {
          articulo = d.Articulo - g.Sum(x => x.ArticuloR) ?? d.Articulo,
          gastos = d.GastosEstudio - g.Sum(x => x.GastosEstudioR) ?? d.GastosEstudio,
          honorarios = d.Honorarios - g.Sum(x => x.HonorariosR) ?? d.Honorarios,
          ivah = d.IVAHonorarios - g.Sum(x => x.IVAHonorariosR) ?? d.IVAHonorarios
          });

这是最好的方法吗?如果你想给我你的意见,欢迎你。

问候!