How can I change this request :
query = query.Where(item => (from table in context.Table
where table.amount == item.Amount
select table).Count() >= 10);
to not use the subquery (from ... in ...) ?
I tried to create the subquery separately, to use it with the Where condition :
var subQuery = from table in context.Table select table.amount;
var list = subQuery.ToList()
But I don't know how I can use it after that, because of the .Count() operation.
Thank you for your comments.
How about this:
query = query.Where(item => context.Table
.Count(t => t.amount == item.Amount) >= 10);
Or to reduce the number of round-trips:
var counts = context.Table
.GroupBy(t => t.amount)
.Select(g => new {amount = g.Key, count = g.Count()});
query = from q in query
join c in counts
on q.amount equals c.amount
where c.count >= 10
select q;
Just use Count with a predicate directly:
query.Where(item => context.Table.Count(table.amount == item.Amount) >= 10);
what about this one
var subQuery = (from table in context.Table select table.amount).ToList();
query = query.Where(item => subQuery.Count() >= 10);
Related
This is my first post and I hope you can help me. I didn't find an answer so here I'm:
I created this query in SQL and it works.
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";
Now I need to do the same but in LINQ. Basically: I have two tables (deudores and recibos). In deudores I have the debt with the different concepts (columns):
gastos, articulo, honorarios, ivahonorarios
In the table recibos I insert the receipts with the same columns.
The SQL query sums the receipts and subtracts the debt. The closest I get in LINQ was this:
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),
});
The problem with this query is that if there is no receipt does not show any information (should show the initial debt)
I try with DefaultIfEmpty but didn't work:
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
});
The problem with this query is that it does not subtract it.
Any suggestion?
Thank you!
You want the equivalent of an outer join, so you correctly turn to a GroupJoin, or join ... into. But the query part ...
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
... does more than you want. In fluent LINQ syntax its structure is equivalent to
bd.deudores.GroupJoin(bd.recibos, ...)
.SelectMany(...)
.GroupBy(...)
The point is that the first GroupJoin creates a collection of deudores, each having a group of their recibos, that may be empty. Then the SelectMany flattens it into pairs of one deudores and one recibos or null. Subsequently, the GroupBy creates groups with null elements.
The first GroupJoin is all you need:
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()
});
By adding DefaultIfEmpty() it is ensured that Sum will return 0 when there are no elements.
#Gert Arnold: The relationship between the two tables is a column name DNI. In the table deudores is PK and in the table recibos is FK. Last night i tried this code and it works:
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
});
Is it the best way to do it ?. If you want to give me your opinion will be welcome.
Regards!
I am having following query here. how do I get similar linq query for this sql.
SELECT *
FROM PublishedLineBar
WHERE PublishedRosterShiftId
IN (SELECT LatestShiftId FROM
( SELECT MAX(PublishedRosterShiftId) as LatestShiftId, DayNumber
FROM PublishedRosterShift
WHERE employeeid = 14454
GROUP BY DayNumber)
as ShiftProjection )
I have used below linq translation, but it is failing somewhere.
var shifts = dbContext.PublishedRosterShifts
.Where(h => h.EmployeeId == EmployeeId);
var inner = shifts
.Select(x => new
{
LatestShiftId = shifts.Max(p => p.PublishedRosterShiftId),
DayNumber = x.DayNumber
})
.GroupBy(s => s.DayNumber)
.Select(g => g.FirstOrDefault());
var q = from f in shifts
select new
{
LatestShiftId = shifts.Max(p => p.PublishedRosterShiftId),
DayNumber = f.DayNumber
};
var query = from l in dbContext.PublishedLineBars
where inner.Select(s => s.LatestShiftId).Contains(l.PublishedRosterShiftId)
select l;
Here is the LINQ equivalent of your subquery used for SQL IN (...) clause (with unnecessary nesting removed):
var inner = dbContext.PublishedRosterShifts
.Where(s => s.EmployeeId == EmployeeId)
.GroupBy(s => s.DayNumber)
.Select(g => g.Max(s => s.PublishedRosterShiftId));
and the query using it:
var query = from l in dbContext.PublishedLineBars
where inner.Contains(l.PublishedRosterShiftId)
select l;
or simply
var query = dbContext.PublishedLineBars
.Where(l => inner.Contains(l.PublishedRosterShiftId));
What you are missing in your attempt is that in SQL SELECT MAX(PublishedRosterShiftId) as LatestShiftId, DayNumber operates on the result of the GROUP BY operator, hence in LINQ the Select should be after GroupBy.
My linq query is:
var query1 = (from grp in ctnx.tblGroupDatas
group grp by grp.MeterID_FK into g
let maxId = g.Max(gId => gId.GroupDataID)
select new { metId = g.Key, maxId });
query2 = (from met in ctnx.tblMet
from mod in ctnx.tblMod.Where(mo => mo.ModID == met.Mod_FK).DefaultIfEmpty()
from grp in ctnx.tblGroupDatas.Where(gr => gr.Met_FK == met.MetID)
from group1 in db.tblMetRelateGroups.Where(x => x.Met_FK == met.MetID)
from q1 in query1.Where(q => q.metId == met.MetID && grp.GroupDataID == q.maxId)
where (group1.GroupMetID_FK == groupID)
select new
{
met.MetID,
mod.ModSerial,
met.MetSerial,
met.MetWaterSharingNo,
met.MetPowerSharingNo,
grp.GroupDate,
grp.GroupDataID
});
var gridobisdata = query2.OrderByDescending(m => m.GroupDate);
but this show error:
The specified LINQ expression contains references to queries that are
associated with different contexts.
I would like to do a group by and on that a sum and a count. I don't seem to be able to create the solution in linq. How can I convert my query to linq?
SELECT HistoricalBillingProductGroup,
COUNT(*),
BillingPeriod,
SUM(TotalMonthlyChargesOtcAndMrc)
FROM [x].[dbo].[tblReport]
group by BillingPeriod, HistoricalBillingProductGroup
order by BillingPeriod
This is what I got sofar in Linq
var result =
context.Reports.GroupBy(x => new {x.BillingPeriod, x.HistoricalBillingProductGroup})
.Select(x => new StatisticsReportLine
{
HistoricalBillingGroup = x.FirstOrDefault().HistoricalBillingProductGroup,
BillingPeriod = x.FirstOrDefault().BillingPeriod,
CountOfRows = x.Count(),
SumOfAmount = x.Sum(p => p.TotalMonthlyChargesOtcAndMrc) ?? 0
})
.ToString();
The query I get from this is enormous and takes a very long time to load. In SQL its a matter of milliseconds. I hardly doubt this is the solution.
I believe the calls to x.FirstOrDefault() are the source of your problem. Each one of these will result in a very costly inner query inside the SELECT clause of the generated SQL.
Try using the Key property of the IGrouping<T> instead :
var result = context.Reports
.GroupBy(x => new {x.BillingPeriod, x.HistoricalBillingProductGroup})
.OrderBy(x => x.Key.BillingPeriod)
.Select(x => new StatisticsReportLine
{
HistoricalBillingProductGroup = x.Key.HistoricalBillingProductGroup,
BillingPeriod = x.Key.BillingPeriod,
CountOfRows = x.Count(),
SumOfAmount = x.Sum(p => p.TotalMonthlyChargesOtcAndMrc) ?? 0
});
Or if you prefer query syntax:
var result =
(from r in context.Reports
group r by new { r.BillingPeriod, r.HistoricalBillingProductGroup } into g
orderby g.Key.BillingPeriod
select new StatisticsReportLine
{
HistoricalBillingProductGroup = g.Key.HistoricalBillingProductGroup,
BillingPeriod = g.Key.BillingPeriod,
CountOfRows = g.Count(),
SumOfAmount = x.Sum(p => p.TotalMonthlyChargesOtcAndMrc) ?? 0
});
You could try this one:
var result = context.Reports
.GroupBy(x => new {x.BillingPeriod, x.HistoricalBillingProductGroup})
.Select(x => new StatisticsReportLine
{
HistoricalBillingGroup = x.Key.HistoricalBillingProductGroup,
BillingPeriod = x.Key.BillingPeriod,
CountOfRows = x.Count(),
SumOfAmount = x.Sum(p => p.TotalMonthlyChargesOtcAndMrc) ?? 0
}).ToString();
In the above query you make a group by on two properties, BillingPeriod and HistoricalBillingProductGroup. So in each group that will be created, you will have a key, that will be consisted by these two properties.
I have this standard piece of LINQ
var sidEvents = (from f in AppDelegate.Self.Subscription.Fred
from s in f.Sid
from e in s.Eve
where e.date >= oneWeek
select new {Title = e.type, Data = e.data, Date = e.date}).ToList();
I've changed a few things and now I get a list of Eve objects with the where condition after it like this
var sidEvents = AppDelegate.Self.DBManager.GetListOfEvents("type", "EatingOut").Where(t => t.date >= oneWeek).ToList();
Is there a way that I can extend this LINQ query to include the select new {...} that was on the original LINQ query?
var sidEvents = AppDelegate.Self.DBManager.GetListOfEvents("type", "EatingOut")
.Where(t => t.date >= oneWeek)
.Select(e => new { Title = e.type, Data = e.data, Date = e.date }).ToList();
Maybe you are looking for this:
var sidEvents = AppDelegate.Self.DBManager.GetListOfEvents("type", "EatingOut")
.Where(t => t.date >= oneWeek)
.Select(e => new {...})
If you are more familiar with the LINQ query syntax, you can
translate the second query from method syntax to query syntax
var sidEvents = (from t in AppDelegate.Self.DBManager.GetListOfEvents("type", "EatingOut")
where t.date >= oneWeek
select t).ToList();
and then replace the select t part with your new expression.