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.
Related
What could be the LINQ query for this SQL?
SELECT PartId, BSId,
COUNT(PartId), MAX(EffectiveDateUtc)
FROM PartCostConfig (NOLOCK)
GROUP BY PartId, BSId
HAVING COUNT(PartId) > 1
I am actually grouping by two columns and trying to retrieve max EffectiveDateUtc for each part.
This is what I could write. Stuck up on pulling the top record based on the date.
Also not sure, if this is a optimal one.
//Get all the parts which have more than ONE active record with the pat
//effective date and for the same BSId
var filters = (from p in configs
?.GroupBy(w => new
{
w.PartId,
w.BSId
})
?.Select(g => new
{
PartId = g.Key.PartId,
BSId = g.Key.BSId,
Count = g.Count()
})
?.Where(y => y.Count > 1)
select p)
?.Distinct()?.ToList();
var filteredData = (from p in configs
join f in filters on p.PartId equals f.PartId
select new Config
{
Id = p.Id,
PartId = p.PartId,
BSId = p.BSId,
//EffectiveDateUtc = MAX(??)
}).OrderByDescending(x => x.EffectiveDateUtc).GroupBy(g => new { g.PartId, g.BSId }).ToList();
NOTE: I need the top record (based on date) for each part. Was trying to see if I can avoid for loop.
The equivalent query would be:
var query =
from p in db.PartCostConfig
group p by new { p.PartId, p.BSId } into g
let count = g.Count()
where count > 1
select new
{
g.Key.PartId,
g.Key.BSId,
Count = count,
EffectiveDate = g.Max(x => x.EffectiveDateUtc),
};
If I understand well, you are trying to achieve something like this:
var query=configs.GroupBy(w => new{ w.PartId, w.BSId})
.Where(g=>g.Count()>1)
.Select(g=>new
{
g.Key.PartId,
g.Key.BSId,
Count = g.Count(),
EffectiveDate = g.Max(x => x.EffectiveDateUtc)
});
I have the following query and is super slow for 3000 records and produces 370 entries. How can I improve performance on it?
dealerResults = _results.GroupBy(x => new { x.DealerName, x.DealerId })
.Select(x => new MarketingReportResults()
{
DealerId = x.Key.DealerId,
DealerName = x.Key.DealerName,
LinkedTotal = linkedLeadCores.Count(y => y.DealerId == x.Key.DealerId),
LeadsTotal = x.Count(),
SalesTotal = x.Count(y => y.IsSold),
Percent = (decimal)(x.Count() * 100) / count,
ActiveTotal = x.Count(y => y.IsActive),
}).ToList();
I think the linkedLeadCores.Count() is the bottleneck here as you loop though the entire linkedLeadCores list each time a entry of _results is processed. This assumption seems to be confirmed by your comments also.
So to remove the bottleneck you could create a map (aka dictionary) that holds the count for each dealer before doing anything with _results like this ...
var linkedLeadCoresCountMap = linkedLeadCores
.GroupBy(y => y.DealerId )
.ToDictionary(y => y.Key, y => y.Count());
... and then you could write
LinkedTotal = linkedLeadCoresCountMap.ContainsKey(x.Key.DealerId) ?
linkedLeadCoresCountMap[x.Key.DealerId] : 0,
Doing a Group Join to linkedLeadCores will use an internal hash table for lookup and should solve your problem.
var dealerResults =
(from r in _results.GroupBy(x => new { x.DealerName, x.DealerId })
join llc in linkedLeadCores on r.Key.DealerId equals llc.DealerId into g
select new MarketingReportResults()
{
DealerId = r.Key.DealerId,
DealerName = r.Key.DealerName,
LinkedTotal = g.Count(),
LeadsTotal = r.Count(),
SalesTotal = r.Count(y => y.IsSold),
Percent = (decimal)(r.Count() * 100) / count,
ActiveTotal = r.Count(y => y.IsActive),
}).ToList();
I'm trying to convert my sql query to linq, i confused about sum and grouping,
this is my query
SELECT
produk.supplier,
SUM(transaksi.jumlah_transaksi),
SUM(transaksi.nominal_transaksi),
operasional.nominal
FROM
transaksi INNER JOIN produk ON transaksi.id_produk = produk.id_produk
LEFT JOIN
(SELECT
operasional.id_supplier,
SUM(nominal) AS nominal
FROM
operasional) operasional
ON operasional.id_supplier = produk.id_supplier
GROUP BY produk.supplier
output should be
like this
Progress
i am just trying with linq query like this without grouping
var result = from t in db.transaksi
join p in db.produk on t.id_produk equals p.id_produk
from op in
(
from o in db.operasional
select new
{
id_supplier = o.id_supplier,
nominal = o.nominal
}
).Where(o => o.id_supplier == p.id_supplier).DefaultIfEmpty()
select new
{
nama_supplier = p.supplier,
jumlah_transaksi = t.jumlah_transaksi,
nominal_transaksi = t.nominal_transaksi,
biaya_operasional = op.nominal
};
and result query from my linq still like this
SELECT
`p`.`supplier`,
`t`.`jumlah_transaksi`,
`t`.`nominal_transaksi`,
`t1`.`nominal`
FROM
`transaksi` `t`
INNER JOIN `produk` `p`
ON `t`.`id_produk` = `p`.`id_produk`
LEFT JOIN `operasional` `t1`
ON `t1`.`id_supplier` = `p`.`id_supplier`
Solved
and this is my full linq
var result = from t in db.transaksi
join p in db.produk on t.id_produk equals p.id_produk
from op in
(
from o in db.operasional
group o by o.id_supplier into g
select new
{
id_supplier = g.First().id_supplier,
nominal = g.Sum(o => o.nominal)
}
).Where(o => o.id_supplier == p.id_supplier).DefaultIfEmpty()
select new
{
nama_supplier = p.supplier,
jumlah_transaksi = t.jumlah_transaksi,
nominal_transaksi = t.nominal_transaksi,
biaya_operasional = op.nominal
};
var grouped = result
.GroupBy(x => x.nama_supplier)
.Select(x => new
{
nama_supplier = x.Key,
jumlah_transaksi = x.Sum(s => s.jumlah_transaksi),
nominal_transaksi = x.Sum(s => s.nominal_transaksi),
biaya_operasional = x.Select(s => s.biaya_operasional).First()
});
Try to use GroupBy (in following code result is your query from code above):
var grouped = result
.GroupBy(x => x.nama_supplier)
.Select(x => new {
nama_supplier = x.Key,
sum1 = x.Sum(s => s.jumlah_transaksi),
sum1 = x.Sum(s => s.nominal_transaksi),
nominal = x.Select(s => s.biaya_operasional).First()
})
Code is not checked so use it just as idea.
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()
});
Simple line:
var x = (from a in arr select a).First();
Console.WriteLine(“First" + x);
How to convert to Lambda expression?
So you want to convert the LINQ query from using query syntax to plain extension method calls?
// var first = (from a in arr select a).First();
var first = arr.First();
// var last = (from a in arr select a).Last();
var last = arr.Last();
// var filtered = (from a in arr where a == 10 select a).First();
// there are a couple of ways to write this:
var filtered1 = arr.Where(a => a == 10)
.First();
var filtered2 = arr.First(a => a == 10); // produces the same result but obtained differently
// now a very complex query (leaving out the type details)
// var query = from a in arr1
// join b in arr2 on a.SomeValue equals b.AnotherValue
// group new { a.Name, Value = a.SomeValue, b.Date }
// by new { a.Name, a.Group } into g
// orderby g.Key.Name, g.Key.Group descending
// select new { g.Key.Name, Count = g.Count() };
var query = arr1.Join(arr2,
a => a.SomeValue,
b => b.AnotherValue,
(a, b) => new { a, b })
.GroupBy(x => new { x.a.Name, x.a.Group },
x => new { x.a.Name, Value = x.a.SomeValue, x.b.Date })
.OrderBy(g => g.Key.Name)
.ThenByDescending(g => g.Key.Group)
.Select(g => new { g.Key.Name, Count = g.Count() });
When you have an expression of the form (from y in x select y), you can almost always write x instead.