LINQ query with distinct count - c#

I am trying to construct a LINQ query in C# that will give me a list of distinct values from a column in a dataset with a count for each row. The results would look like this.
State Count
AL 55
AK 40
AZ 2
Here is the SQL that does that.
SELECT name, COUNT(*) AS count
FROM architecture arch
GROUP BY name
ORDER BY name
I've figured out the LINQ to get the DISTINCT values which is.
var query = ds.Tables[0].AsEnumerable()
.OrderBy(dr1 => dr1.Field<string>("state"))
.Select(dr1 => new {state = dr1.Field<string>("state")})
.Distinct().ToList();
But I can't figure out how to get the COUNT(*) for each distinct value to work in LINQ. Any idea how I can add that into the LINQ query?

You need to group your results based on State and the Select count from the group like:
var query = ds.Tables[0].AsEnumerable()
.GroupBy(r => r.Field<string>("state"))
.Select(grp => new
{
state = grp.Key,
Count = grp.Count()
})
.OrderBy(o => o.state)
.ToList();

Group all rows by value of state column. Then order groups by grouping key. And last step - project each group into anonymous object with grouping key (state) and count of rows in group:
var query = ds.Tables[0].AsEnumerable()
.GroupBy(r => r.Field<string>("state"))
.OrderBy(g => g.Key)
.Select(g => new { State = g.Key, Count = g.Count() })
.ToList();
Query syntax will look like (I'll skip converting to list, to avoid mixing syntaxes):
var query = from r in ds.Tables[0].AsEnumerable()
group r by r.Field<string>("state") into g
orderby g.Key
select new {
State = g.Key,
Count = g.Count()
};

I think you need GroupBy
var query = ds.Tables[0].AsEnumerable()
.GroupBy(dr1 => dr1.Field<string>("state"))
.Select(g => new {state = g.Key, count = g.Count())
.ToList();

Why bother with Distinct, when you can translate your SQL query to LINQ almost word-for-word? You can do it like this:
var query = ds.Tables[0].AsEnumerable()
.GroupBy(dr1 => dr1.Field<string>("state"))
.Select(g => new {
State = g.Key
, Count = g.Count()
})
.OrderBy(p => p.State)
.ToList();
This produces a list of {State, Count} pairs. If you prefer a dictionary of state-to-count, you can change your query like this:
var query = ds.Tables[0].AsEnumerable()
.GroupBy(dr1 => dr1.Field<string>("state"))
.ToDictionary(g => g.Key, g => g.Count());

var query = ds.Tables[0].AsEnumerable()
.GroupBy(x=>x.Field<string>("state"))
.Select( g => new{
state = g.Key,
count = g.Count()
});

Guess what, the equivalent of group by is group by :)
var query = from dr1 in ds.Tables[0].AsEnumerable()
group dr1 by dr1.Field<string>("state") into state
select new { State = state.Key, Count = state.Count() };

var stat = from row in ds.Tables[0].AsEnumerable()
group row by new
{
Col1 = row["Name"],
} into TotalCount
select new
{
ActionName = TotalCount.Key.Col1,
ActionCount = TotalCount.Count(),
};

Related

how to use Linq count with group by in C#

i have a datatable in which look like this
basically i want it to be group by column featurename(distinct) in which it should sum in effort and complete column
specify all the featureid,featurename comma sepratedcount of the featureid
assigned to comman seprated
now i want datatable to be look like this
don't know how to use the count
code
var result5= dtTaskandBugs.AsEnumerable().GroupBy(x => x["Functional Area"])
.Select(item => new
{
FunctionalArea = item.Key,
Completedsum = item.Sum(y => Convert.ToDecimal(y["Completed"])),
effortsum = item.Sum(z => Convert.ToDecimal(z["effort"])),
storyids = string.Join(",", item.Select(a => a["Storyid"]).Distinct()),
storiesename= string.Join(",", item.Select(b => b["StoryName"]).Distinct()),
Featureid = string.Join(",", item.Select(c => c["Featureid"]).Distinct()),
Featurename= string.Join(",", item.Select(d => d["FeatureName"]).Distinct()),
});
With Count() you will get count of grouped value.
Try with Linq like this:
from s in dtTaskandBugs.AsEnumerable()
group s by s.Field<string>("Functional Area")
into grp
orderby grp.Key
select new {
FunctionalArea = grp.Key,
Completedsum = grp.Sum(y => Convert.ToDecimal(y["Completed"])),
effortsum = grp.Sum(z => Convert.ToDecimal(z["effort"])),
storyids = string.Join(",", grp.Select(a => a["Storyid"]).Distinct()),
storiesename= string.Join(",", grp.Select(b => b["StoryName"]).Distinct()),
Featureid = string.Join(",", grp.Select(c => c["Featureid"]).Distinct()),
Featurename= string.Join(",", grp.Select(d => d["FeatureName"]).Distinct()),
Count = grp.Count() // <----------------
};
Just write item.count() and you will get count of grouped values,

LINQ Query with GroupBy, MAX and Count

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)
});

Group by percentage in LINQ

I try to create the following SQL query in LINQ to use in my ASP MVC project:
SELECT State, (Count(a.State)* 100 / (Select Count(*) From myTable))
FROM myTable a
GROUP BY a.State
What I have so far:
var data = db.myTable.GroupBy(fu => fu.State)
.Select(g => new { Label = g.Key, Value = g.Key * 100 / g.Count() })
.ToList();
The calculation is not correct. Have to get LINQ producing the same results as SQL?
Probably this:-
Value = g.Count() * 100 / db.myTable.Count()
This seems to be equivalent of your SQL query.
So your complete query should look like:-
var data = db.myTable.GroupBy(fu => fu.State)
.Select(g => new { Label = g.Key, Value = g.Count() * 100 / db.myTable.Count() })
.ToList();
You can try this:
var data = db.myTable.GroupBy(fu => fu.State)
.Select(g => new { Label = g.Key, Value = g.Count() * 100 / db.myTable.Count() })
.ToList();
g.Count() is going to give you Count(a.State) value and db.myTable.Count() the total of rows in that table

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.

How do I get a lambda query that is like this tsql query?

Having a T-SQL query:
select [ProductNumber] ,max([ProductRevNumber])
from Products
group by [ProductNumber]
Attempted LINQ query:
ProductsDBContext.Products.GroupBy(x => x.ProductRevNumber)
.Select(group => ProductNumber,
ProductRevNumber = group.Max(x => x.ProductRevNumber));
The lambda query doesn't work.
I think this is what you are after:
var latestProducts = ProductsDBContext.Products
.GroupBy(p => p.ProductNumber).Select(g => new
{
ProductNumber = g.Key,
MaxProductRevNumber = g.Max(p => p.ProductRevNumber))
});
from p in db.Products
group p by p.ProductNumber into g
select new
{
ProductNumber = g.Key,
ProductRevNumber = g.Max(p => p.ProductRevNumber)
};

Categories

Resources