Group by Linq . Count of Key field - linq

select
count(di.field1) as myCount,
di.field2
from di
group by di.field2
Im trying to understand the concept of this :
group di.field2 by new { di.field1, di.field2 } into g
select new
{
documentID = g.Key.field2,
docCount = g.Count(????)
});
How do i get the value of the field1 count ?

Perhaps something like this:
group di by di.field2 into g
select new
{
documentID = g.Key,
docCount = g.Select(c => c.field1).Count()
});

from p in di
group p by p.field2 into g
select new { field2 = g.Key, field2Count = g.Count() };
Check this., This should work

Do you need to do the grouping to get the field count? Can't you just do:
var count=di.field1.Count;

Related

Convert multiple rows into single in datatable

I have a DataTable in C# with two columns
State Region
A 1
A 2
B 3
B 4
What I want to achieve is
State Region
A 1,2
B 3,4
Is this possible in C# with a single LINQ query?
I am not good in LINQ and also don't want to loop through table to achieve that.
var result = dataTable.AsEnumerable()
.GroupBy(row => row.Field<string>("State"))
.Select(g =>
{
var row = dataTable.NewRow();
row.ItemArray = new object[]
{
g.Key,
string.Join(",",
g.Select(r => r.Field<string>("Region")))
};
return row;
}).CopyToDataTable();
Use GroupBy to achieve this as follow....
var groupedData = from b in dataTable.AsEnumerable()
group b by b.Field<string>("State") into g
select new
{
State = g.Key,
Regions = g,
};
Then you can iterate through each group to get Data...
foreach (var g in groupedData)
{
foreach (var w in g.Regions)
{
Console.WriteLine(w);
}
}

How to join two datasource which return all rows and group by condition?

I have a problem when using LINQ to join two datasource. Two datasource created by a query like :
var A = (from....
group .... into grp
select new
{
Qty = grp.Count(),
Code = grp.Key.Code,
Name = grp.Key.Name
});
var B = (from....
group .... into grp
select new
{
Qty = grp.Count(),
Code = grp.Key.ContCode,
Name = grp.Key.ContName
});
Value of 'A' will be returned like this :
Qty-Code-Name
1-10A-Cont10
1-20B-Cont20
1-30C-Cont30
Value of 'B' will be returned like this :
Qty-Code-Name
1-10A-Cont10
1-20B-Cont20
1-30C-Cont30
1-40D-Cont40
1-50E-Cont50
I want to join A and B (or do somethings) and the result like this (which sum column 'Qty' if they have the same 'Code' and 'Name') :
Qty-Code-Name
2-10A-Cont10
2-20B-Cont20
2-30C-Cont30
1-40D-Cont40
1-50E-Cont50
How can I do it ? Please help me.
Thank you very much !
Concat the two datasources and than group by code and name.
Something like:
var q = from v in A.Concat(B)
group v by new {v.Code,v.Name } into g
select new
{
Qty = g.Sum(a => a.Qty),
CodeName = g.Key.Code,
Name = g.Key.Name
};

how can this SQL be done in LINQ?

i have this simple SQL query...
-- BestSeller
SELECT TOP(1) v.make, v.model, COUNT(v.make) AS NoSold
FROM Vehicles v
group by v.make, v.model
order by NoSold DESC
Im using entity framwork and want to do the same thing using linq. so far i have...
var tester = (from v in DB.VP_Historical_Vehicles
group v by v.make into g
orderby g.Count() descending
select new { make = g.Key, model = g, count = g.Count() }).Take(1);
foreach(var t in tester)
{
BestSeller.Make = t.make;
BestSeller.Model = t.make;
BestSeller.CountValue = t.count;
}
i keep getting timeouts, the database is large but the SQL runs very quick
any sugestions?
thanks
truegilly
Group by a compound key.
var t = (
from v in DB.VP_Historical_Vehicles
group v by new { v.make, v.model } into g
orderby g.Count() descending
select new { make = g.Key.make, model = g.Key.model, count = g.Count() }
)
.First();
BestSeller.Make = t.make;
BestSeller.Model = t.make;
BestSeller.CountValue = t.count;
Check what queries it performs when you run it with LINQ.
I suspect that you orderby g.Count() descending might be executing a COUNT query for each row and that would take a toll on performance to say the least.
When working with EF, always check what your LINQ statements produce in terms of queries. It is very easy to create queries that result in a n+1 scenario.
thanks to Scott Weinstein answer i was able to get it working
please comment if there is a more efficiant way of doing this...
VehicleStatsObject BestSeller = new VehicleStatsObject();
using (var DB = DataContext.Get_DataContext)
{
var t = (from v in DB.VP_Historical_Vehicles
group v by new { v.make, v.model } into g
orderby g.Count() ascending
select new { make = g.Key.make, model = g.Key.model, count = g.Count() }).OrderByDescending(x => x.count).First();
BestSeller.Make = t.make;
BestSeller.Model = t.model;
BestSeller.CountValue = t.count;
}
return BestSeller;

Linq extract a count() value from a data object

I have divAssignments that has potential multiple rows by rNI, an official id, according to a compound key of Indictment and booking numbers.
rNI Booking Indictment
12345 954445 10 12345
12345 954445 10 12346
12345 954445 10 12347
So ID has a count of 3 for a single booking number for this rni.
I get lost attempting to generate a count and a group by booking Number:
var moreThen = from dA in divAssignments
select new { dA.rNI, IndictmentCount = dA.indictmentNumber.Count() };
Most of the examples are dealing with static int[] and don't seem to work in my case.
How do I get a group and then a count? If I could put in a having that would be fantastic.
from a t-sql POV I'd use this:
Select rni, bookingNumber, count(*) IndictmentCount
from divAssignments
group by rni, bookingNumber
having count(*) > 0
TIA
How about something like this:
var query = from item in divAssignments
group item by item.rNI into grouping
select new
{
Id = grouping.Key,
Count = grouping.Count()
}
If you're interested in grouping by both the rNI and the booking number, I would change it to this:
var query = from item in divAssignements
group item by new { item.rNI, a.Booking } into grouping
select new
{
Id = grouping.Key,
Count = grouping.Count
};
OR
var query = from item in divAssignments
group item by item into grouping
select new
{
Id = grouping.Key,
Count = grouping.Count()
}
and implement IEquatable on the divAssignment object to support equality comparison. The other option if you'd like is to write an IEqualityComparer instance to do the composite key comparison. Your query could then look like:
var query =
divAssignments
.GroupBy(i => i, new MyCustomEqualityComparer())
.Select(i => new { Key = i.Key, Count = i.Count());
var query =
from dA in divAssignments
group dA by new { dA.rNI, dA.bookingNumber };
foreach(var grp in query)
{
Console.WriteLine("rNI={0}, bookingNumber={1} => Count={2}", grp.Key.rNI, grp.Key.bookingNumber, grp.Count());
}
If you use a Grouping operator in Linq you will get what you need. The code:
var count = from a in divAssignments
group a by new { a.rNI, a.Booking } into b
select b;
will return a collection of IGrouping objects. This will give you the Key (in my example this will be an anonymous type with an rNI and a Booking property) and a collection of the divAssignments that match the key.
Using Method syntax (much easier to read in my opinion):
First group the records, then select a new result for each group that contains the count.
var groups = divAssignments.GroupBy(d => new { d.rNI, d.Booking });
groups.Select(g=> new { g.Key.rNI, g.Key.Booking, IndictmentCount = g.Count() });

LINQ to remove duplicated property

I have a LINQ statement like this:
var media = (from p in postService.GetMedia(postId)
select new
{
PostId = postId,
SynthId = p.SynthId
});
There are many(possibly thousands) of records returned with the same SynthId. I want to select one one, any random one. So when I'm finished, media should contain records with distinct SynthId.
SynthId can be null, I want all nulls to be in media (the distinct should not affect them).
My DAL is EntityFramework, if that will help.
How do I accomplish this in the most efficient way?
Use a grouping query:
var media =
from p in postService.GetMedia(postId)
group p by p.SynthId into g
select g.First();
This will give you the first post in the sequence for each group of records, where the grouping key is the SynthId.
If it's important for you to do a projection (i.e. to use select new { ... }) then you should be able to use the let keyword:
var media =
from p in postService.GetMedia(postId)
group p by p.SynthId into g
let firstPost = g.First()
select new { PostId = firstPost.PostId, SynthId = firstPost.SynthId };
If you want all null values for SynthId to be in their own group, then I would probably filter the first list and then do a concatenation, i.e.:
var media = postService.GetMedia(postId);
var myMedia =
(from p in media
where p.SynthId != null
group p by p.SynthId into g
let firstPost = g.First()
select new { PostId = firstPost.PostId, SynthId = firstPost.SynthId })
.Concat
(from p in media
where p.SynthId == null
select new { PostId = firstPost.PostId, SynthId = firstPost.SynthId });

Resources