C# LINQ Check sum of columns in the same query - c#

Is there a way to check if the sum of PREM_A or PREM_B is not 0 in the same LINQ query and not in a separate LINQ query like the one below i.e. matchRows?
var resultsDt = dt.AsEnumerable().GroupBy(row => new
{
Id = row.Field<string>("ID")
}).Select(grp =>
{
DataRow newRow = dt.NewRow();
newRow["ID"] = grp.Key.Id.Trim();
newRow["PREM_A"] = grp.Sum(r => r.Field<decimal>("PREM_A"));
newRow["PREM_B"] = grp.Sum(r => r.Field<decimal>("PREM_B"));
return newRow;
}).CopyToDataTable();
var matchRows = resultsDt.Select().Where(x => x.Field<decimal>("PREM_A") != 0 || x.Field<decimal>("PREM_B") != 0);
foreach (DataRow row in matchRows)
{
//do something
}

You don't need to convert to a data table for every step, it would be easier to query if you moved away from that.
var query =
from row in dt.AsEnumerable()
group new
{
premA = row.Field<decimal>("PREM_A"),
premB = row.Field<decimal>("PREM_B"),
} by row.Field<string>("ID").Trim() into g
let premA = g.Sum(x => x.premA)
let premB = g.Sum(x => x.premB)
where premA != 0M || premB != 0M
select new
{
Id = g.Key,
PremA = premA,
PremB = premB,
};

Also:
var resultsDt = dt.AsEnumerable()
.GroupBy(row => row.Field<string>("ID"))
.Select(grp =>new {Id= grp.Key,
PREM_A= grp.Sum(r => r.Field<decimal>("PREM_A")),
PREM_B=grp.Sum(r => r.Field<decimal>("PREM_B"))
})
.Where(e=>e.PREM_A!=0 || e.PREM_B!=0);

Related

Linq to find lasted record in group

I want add a new column to find which is lasted record in group.
Can I write subquery in Select() method?
I have try this
var test = DailyPeriods.Where(x => x.BookingDate == "2016/12/30")
.Select(x =>
new
{
PERIOD_GROUP_ID = x.PeriodGroupID,
PERIOD_NAME = x.PeriodName,
New_Column = DailyPeriods
.Where(z => z.BookingDate == "2016/12/30")
.Select(a =>
new
{
PeriodGroupID = a.PeriodGroupID,
period_name = a.PeriodName
}
)
.GroupBy(b => b.period_name)
.Select(g => g.Last().PeriodGroupID)
.Contains(x.PeriodName)
})
But will occur this error
"column not in scope: A:2211708.C(BOOKING_DATE)"
Try this..
var lastRecords = periodList.GroupBy(l => l.PeriodName)
.Select(x => new { PeriodName = x.Key,
PeriodGroupId = x.OrderBy(l => l.PeriodGroupId).Last().PeriodGroupId});
var result = from period in periodList
from lastRec in lastRecords.Where(r => r.PeriodGroupId == period.PeriodGroupId
&& r.PeriodName == period.PeriodName)
.DefaultIfEmpty()
select new { period.PeriodGroupId,period.PeriodName, New_Column=lastRec==null?false:true };

Order by Total Value on LinQ

I want to order my Linq GroupBy statement but the item that has the more Total Descending but i can't make it
This is my LinQ
foreach (var item in db
.Pos.Where(r => r.Fecha.Day <= today.Day)
.Select(g => new { Pdv = g.Pdv, Total = g.Total })
.GroupBy(l => l.Pdv)
.AsEnumerable()
.Select(z => new {
Punto_De_Venta=z.Key,
Total = String.Format("{0:$#,##0.00;($#,##0.00);Zero}",
Decimal.Round(z.Sum(l => l.Total), 0))
}))
{
listadepuntos.Add(item.ToString());
}
var grupoPdv = new SelectList(listadepuntos.ToList());
ViewBag.GroupS = grupoPdv;
The Out put of my Linq Statement is :
Punto_De_Venta = Central, Total = 42,143.00
Punto_De_Venta = Restaurante, Total = 189,949.00
Punto_De_Venta = Venta Moto, Total = 89,678.00
And the Output im looking for is:
Punto_De_Venta = Restaurante, Total = 189,949.00
Punto_De_Venta = Venta Moto, Total = 89,678.00
Punto_De_Venta = Central, Total = 42,143.00
How can i do this?? i cant find a way to make this
The List<> does guarantee ordering, sort the List before passing to your SelectList
var grupoPdv = new SelectList(listadepuntos.OrderByDescending(l=>l.Total).ToList());
ViewBag.GroupS = grupoPdv;
Another approach :
Modify source query to return a sorted list.
var results = db.Pos.Where(r => r.Fecha.Day <= today.Day)
.Select(g => new { Pdv = g.Pdv, Total = g.Total })
.GroupBy(l => l.Pdv).AsEnumerable()
.Select(z => new { Punto_De_Venta=z.Key, Total = String.Format("{0:$#,##0.00;($#,##0.00);Zero}", Decimal.Round(z.Sum(l => Total), 0))})
.OrderByDescending(l=>l.Total)
.ToList();
Once you get the sorted list you can create your SelectList with sorted result.
var grupoPdv = new SelectList(result);
ViewBag.GroupS = grupoPdv;
You'll need to do something like this:
foreach (var item in db.Pos.Where(r => r.Fecha.Day <= today.Day)
.Select(g => new { Pdv = g.Pdv, Total = g.Total })
.GroupBy(l => l.Pdv)
.AsEnumerable()
.Select(z => new { Punto_De_Venta = z.Key, Total = z.Sum(l => l.Total) })
.OrderByDescending(r => r.Total)
.Select(r => new { Punto_De_Venta = r.Punto_De_Venta, Total = String.Format("{0:$#,##0.00;($#,##0.00);Zero}", Decimal.Round(z.Sum(l => l.Total), 0))})
{
listadepuntos.Add(item.ToString());
}

How to remove specefic rows from linq result

I have this Linq to Entity:
var sitesGrpByClientAndFreq = from cfr in clientFullReview2
group cfr by new { cfr.inspectionFreqvency } into g
select new
{
inspectionFreqvency = g.Key.inspectionFreqvency,
siteCount = g.Select(x => x.siteId).ToArray().Distinct().Count(),
normalSitesCount = g.Where(x => x.isNormal == true).Select(x=>x.isNormal).ToArray().Count(),
}
From the above linq I get this result:
My question is How can I remove all rows where inspectionFrequency = -1?
You can mix and match the let keyword with where. It could be something like:
var sitesGrpByClientAndFreq =
from cfr in clientFullReview2
group cfr by new { cfr.inspectionFreqvency } into g
let inspectionFreqvency = g.Key.inspectionFreqvency
where inspectionFreqvency != -1
select new
{
inspectionFreqvency = inspectionFreqvency,
siteCount = g.Select(x => x.siteId).ToArray().Distinct().Count(),
normalSitesCount = g.Where(x => x.isNormal == true).Select(x=>x.isNormal).ToArray().Count(),
}

Converting SQL to Linq with groupby, sum and count

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.

Translating SQL to lambda with groupby

I'm trying to translate this sql statement
SELECT row, SUM(value) as VarSum, AVG(value) as VarAve, COUNT(value) as TotalCount
FROM MDNumeric
WHERE collectionid = 6 and varname in ('C3INEV1', 'C3INEVA2', 'C3INEVA3', 'C3INVA11', 'C3INVA17', 'C3INVA19')
GROUP BY row
into an EF 4 query using lambda expressions and am missing something.
I have:
sumvars = sv.staticvararraylist.Split(',');
var aavresult = _myIFR.MDNumerics
.Where(r => r.collectionid == _collid)
.Where(r => sumvars.Contains(r.varname))
.GroupBy(r1 =>r1.row)
.Select(rg =>
new
{
Row = rg.Key,
VarSum = rg.Sum(p => p.value),
VarAve = rg.Average(p => p.value),
TotalCount = rg.Count()
});
where the staticvararraylist has the string 'C3INEV1', 'C3INEVA2', 'C3INEVA3', 'C3INVA11', 'C3INVA17', 'C3INVA19' (without single quotes) and the _collid variable = 6.
While I'm getting the correct grouping, my sum, average, & count values aren't correct.
You didn't post your error message, but I suspect it's related to Contains. I've found that Any works just as well.
This should get you quite close:
var result =
from i in _myIFR.MDNumerics
where i.collectionid == _collid && sumvars.Any(v => i.varname == v)
group i by i.row into g
select new {
row = g.Key,
VarSum = g.Sum(p => p.value),
VarAve = g.Average(p => p.value),
TotalCount = g.Count()
};
Try this:
var aavresult = _myIFR.MDNumerics
.Where(r => r.collectionid == _collid && sumvars.Contains(r.varname))
.GroupBy(r1 =>r1.row,
(key,res) => new
{
Row = key,
VarSum = res.Sum(r1 => r1.value),
VarAve = res.Average(r1 => r1.value),
TotalCount = res.Count()
});

Categories

Resources