Below I have table - Company
id name value year
1 IBM 10 2011
2 IBM 30 2012
3 IBM 10 2012
4 C 10 2010
I want to group records by name and from each group return only one record with maximum id. All results combine into the list of companies using linq where year is greater 2011. For my example output should be - "3 IBM 10 2012"
I did write something but does not working.
var a = from x in companies where x.year > 2011
group x by new {x.name, x.value, x.ID, x.year } into g
select new {
g.Key.name,
g.Key.value,
g.Max(a=>a.ID),
g.Key.value
};
return a.ToList();
Try this:
var a = from x in companies
where x.Year > 2011
group x by new { x.Name } into g
from x1 in companies
where x1.ID == (from x2 in g select x2.ID).Max()
select x1;
Or something more efficient:
var a = from x in companies
where x.Year > 2011
group x by new { x.Name } into g
join x2 in companies on (from x3 in g select x3.ID).Max() equals x2.ID
select x2;
Don't include the ID in your grouping. In fact, if you just want them grouped by company name, don't include any of those other properties either:
// set up for testing
var companies =
from c in new[]{"1,IBM,10,2011", "2,IBM,30,2012", "3,IBM,10,2012", "4,C,10,2010"}
let cp = c.Split(',')
select new {id=int.Parse(cp[0]), name=cp[1], value=int.Parse(cp[2]), year=int.Parse(cp[3])};
// query
var q = from x in companies where x.year > 2011
group x by x.name into g
let top = g.OrderByDescending(x => x.id).FirstOrDefault()
select new {
top.name,
top.value,
top.id,
top.year
};
Related
Hi I have some two tables,
Product:
ProductID | IssueDate | Amount
1 2017-06-01 1000
2 2017-06-01 1000
3 2017-06-02 500
and Credit:
ProductID | Amount
1 500
1 500
2 1000
3 500
if I use query like this from SQL Server:
SELECT p.IssueDate, SUM(p.Amount), SUM(p.Total)
FROM (SELECT p.IssueDate, SUM(p.Amount) AS Amount,
(SELECT TOP 1 SUM(c.Amount) FROM Credit c WHERE p.Id = c.ProductId) AS Total from Product p
GROUP BY p.IssueDate, p.Id) p
GROUP BY p.IssueDate
I get this result:
IssueDate | Amount | Total
2017-06-01 2000 2000
2017-06-02 500 500
In C# Linq I can get this data by two queries like this:
var data = from p in Products.Collection
select new
{
Product = p,
Credits = Credit.Collection.Where(c => c.ProductID == p.ID).Sum(c => c.Amount)
};
var result = from d in data
group d by new
{
IssueDate = d.Product.IssueDate
} into gr
select new
{
IssueDate = gr.Key.IssueDate,
Credits = gr.Sum(s => s.Credits),
Total = gr.Sum(s => s.Product.Amount)
};
var test = result.ToList();
Does anyone know a better (simpler) solution to get this result? Maybe in one query?
How about:
Products.Collection.GroupBy(x => x.IssueDate)
.Select(x => new
{
IssueDate = x.Key,
Amount = x.Sum(p => p.Amount),
Total = Credit.Collection.Where(c => x.Any(p => p.ProductID == c.ProductID)).Sum(c => c.Amount)
}).ToList();
I have a data table with release plans for every product:
I'd like to calculate amount sum for every single product in every single quarter using linq. In SQL I'd use:
How can I do that in linq?
I tried this code:
public List<ValuePairPlanned> GetQuantityOfEachProductPlannedForRelease(int departmentId)
{
var amountByProducts = (from rp in _context.ReleasePlans
join p in _context.Products
on rp.ProductProductId equals p.ProductId
where rp.DepartmentDepartmentId == departmentId
group new { rp, p } by new { rp.ProductProductId, p.ProductId, p.ProductName, rp.DateTime, rp.Amount }
into grp
select new
{
grp.Key.ProductName,
grp.Key.DateTime,
PlannedAmount = grp.Sum(g => g.rp.Amount)
}).Distinct().ToList().ConvertAll(x => new ValuePairPlanned()
{ PlannedAmount = x.PlannedAmount, Quarter = (x.DateTime.AddDays(2).Month - 1) / 3 + 1, ProductName = x.ProductName });
return amountByProducts;
}
but as a result I get amount value for every products in every quarter. How can I fix it? Thanks for any help.
Since you are using Entity Framework, look into DbFunctions so that you can do the date addition on the SQL Server. If you do not use DbFunctions, then you will have to first fetch your joined tables via ToList() and then do the data math to calculate quarter.
The following should get you very close:
var amountByProducts = from p in _context.Products
join rp in _context.ReleasePlans
on p.ProductId equals rp.ProductId
where rp.DepartmentDepartmentId == departmentId
group new
{
p.ProductName,
Quarter = (DbFunctions.AddDays(rp.DateTime,2).Month - 1) / 3 + 1,
rp.Amount
}
// group all product plans in a given quarter
by new
{
p.ProductName, // shouldn't this be ProductId?
Quarter = (DbFunctions.AddDays(rp.DateTime,2).Month - 1) / 3 + 1
}
into grp
// from the grouped entries, sum the amounts
select new ValuePairPlanned()
{
PlannedAmount = grp.Sum(g => g.Amount),
Quarter = grp.Key.Quarter,
ProductName = grp.Key.ProductName
};
return amountByProducts.ToList();
Good morning all,
I have been stuck on this all morning and feel like I've hit a wall. I'd love any advice that can be given at this point.
My table is basically as follows:
PatientName|LivingSpace
-----------|-----------
Patient 1 | Unit 1
Patient 2 | Unit 1
Patient 3 | Unit 2
Patient 4 | Unit 2
Patient 5 | Unit 3
Patient 6 | Unit 3
Patient 7 | Unit 3
Patient 8 | Unit 3
I need a LINQ to SQL query to illustrate this:
Unit|Count
----|-----
Unit 1 | 2
Unit 2 | 2
Unit 3 | 4
TOTAL | 8
My SQL query works fine, I'm just having issues with converting it to LINQ:
SELECT LivingSpace, COUNT(LivingSpace) AS LivingSpace
FROM PatientTable
WHERE Status = 'Active'
GROUP BY LivingSpace
UNION ALL
SELECT 'SUM' LivingSpace, COUNT(LivingSpace)
FROM PatientTable
var counts = from x in ctx.PatientTable
group x by x.LivingSpace into y
select new { Key = y.Key Count = y.Count() };
var total = new { Key = "Total" , Count = ctx.PatientTable.Count() };
var full = counts.ToList();
full.Add(total);
If you want to do it all in one query the following should work (adjusting for the actual names of your properties of course).
context.PatientTable.GroupBy(a => a.LivingSpace.Name, a => 1)
.Select(a => new
{
a.Key,
Total = a.Sum(q => q)
})
.Union(PatientTable.Select(a => new
{
Key = "Total",
Total = PatientTable.Count()
}))
var report = patients
.GroupBy(p => p.LivingSpace)
.Select(g => new
{
Unit = g.Key,
Count = g.Count()
})
.Union(patients
.Select(p => new
{
Unit = "Total",
Count = patients.Count
}));
Something like this should work and just run one query.
var results = db.PatientTable
.GroupBy(p => p.LivingSpace)
.Select(grp => new
{
Unit = grp.Key,
Count = grp.Count()
})
.Union(db.PatientTable
.GroupBy(p => 1)
.Select(grp => new
{
Unit = "Total",
Count = grp.Count()
}));
I see you got the answer, but for learning purposes, here is side by side conversion.
Your SQL (with some aliases added for better comparison)
SELECT P.LivingSpace, COUNT(P.*) AS Count
FROM PatientTable AS P
WHERE P.Status = 'Active'
GROUP BY P.LivingSpace
UNION ALL
SELECT 'SUM' AS LivingSpace, COUNT(P.*) AS Count
FROM PatientTable AS P
The same single query in LINQ
var query =
(
from p in db.PatientTable
where p.Status = "Active"
group p by p.LivingSpace into g
select new { LivingSpace = g.Key, Count = g.Count() }
)
.Concat
(
from p in db.PatientTable
group p by "SUM" into g
select new { LivingSpace = g.Key, Count = g.Count() }
);
I'm using the following LINQ to select data from a table:
(from m in entity.Results
where m.Group == 0 ||
m.Group == 1
orderby m.Points descending
select m);
This gives me a result of all Users who are in Group 1 or 2. With that i can display the points they have. But this shows me the points they have in Group 1 and Group 2 separately.
How can i group them and display the total points they have? So instead of this (What i have now):
user1 - group1 - 10
user1 - group2 - 7
user2 - group1 - 7
user2 - group2 - 5
I want this:
user1 - total: 17
user2 - total: 12
How do i have to adjust my query to get a result set like that?
You need to group the users, then use Sum to calculate the TotalPoints:
from m in entity.Results
where m.Group == 0 || m.Group == 1
group m by m.User into g
let TotalPoints = g.Sum(m => m.Points)
orderby TotalPoints descending
select new { User = g.Key, Username = g.Key.Username, TotalPoints };
entity.Results
.Where(m => m.Group == 0 || m.Group == 1)
.GroupBy(m => m.UserID)
.Select(m => new { User = m.Key, TotalPoints = m.Sum(v => v.Points) })
.OrderByDescending(m => m.TotalPoints);
Hi Vivendi use this(Please edit according to your requirement)
var q = (from h in entity.Results
group h by new { h.UserID} into hh
select new {
hh.Key.UserID,
Score = hh.Sum(s => s.Points )
}).OrderByDescending(i => i.Points);
Output
total: 17
total: 12
Another example with more than one sum and a join
from e in _context.LearnResults
join c in _context.Country on e.CountryId equals c.CountryId
where c.DomainId.Equals("xx")
group e by e.Country.Name into newCountry
let Approved = newCountry.Sum(e => e.Approved)
let Total = newCountry.Sum(e => e.Total)
select new LearnResults() { CountryName = newCountry.Key, Approved= Approved, Total=Total };
I want to use LINQ to group data from a DataTable (columns: userid, chargetag, charge).
The content could look like this:
userid chargetag charge
-----------------------------
user1 tag3 100
user2 tag3 100
user3 tag5 250
I need something like this as a result:
chargetag count sum
-------------------------
tag3 2 200
tag5 1 250
This is what I have so far:
var groupedData = from b in dataTable.AsEnumerable()
group b by b.Field<string>("chargetag") into g
let count = g.Count()
select new
{
ChargeTag = g.Key,
Count = count,
};
I can extract the name of the chargetag and the number of it.
How would I have to change the LINQ query to access the sum of charges as well?
Thanks in advance :-)
Regards,
Kevin
That's pretty easy - just use the Sum extension method on the group.
var groupedData = from b in dataTable.AsEnumerable()
group b by b.Field<string>("chargetag") into g
select new
{
ChargeTag = g.Key,
Count = g.Count(),
ChargeSum = g.Sum(x => x.Field<int>("charge"))
};
(I've removed the let clause here as it wasn't really buying you anything.)
Now that may be inefficient; it may end up grouping twice in order to perform two aggregation operations. You could fix that like with a query continuation like this, if you really wanted:
var groupedData = from b in dataTable.AsEnumerable()
group b by b.Field<string>("chargetag") into g
select new
{
ChargeTag = g.Key,
List = g.ToList(),
} into g
select new
{
g.ChargeTag,
Count = g.List.Count,
ChargeSum = g.List.Sum(x => x.Field<int>("charge"))
};
Or with a let clause instead:
var groupedData = from b in dataTable.AsEnumerable()
group b by b.Field<string>("chargetag") into g
let list = g.ToList()
select new
{
ChargeTag = g.Key,
Count = list.Count,
ChargeSum = list.Sum(x => x.Field<int>("charge"))
};