ID UserName BookType BookID
1 Krish 1 1
1 Krish 1 2
1 Krish 2 1
1 Krish 2 2
2 Ram 1 1
3 Raj 1 1
3 Raj 1 2
I have above table and I want to get the distinct BookType count and BookID count for each user, I am able to write this in SQL Server but when I come to LINQ I am unable to write the query.
I need the following output
ID UserName BookType BookID
1 Krish 2 2
2 Ram 1 1
3 Raj 1 2
This should give you correct result:-
var result = Userlist.GroupBy(x => new { x.ID, x.UserName })
.Select(x => new
{
ID = x.Key.ID,
UserName = x.Key.UserName,
BookType = x.Max(z => z.BookType),
BookId = x.Max(z => z.BookId)
});
Update:
Although you agreed to answer, I somehow missed your requirement and the answer which I posted above is wrong since it fetch the maximum BookType & BookId. Below is the query to fetch the distinct count:-
var result = Userlist.GroupBy(x => new { x.ID, x.UserName })
.Select(x => new
{
ID = x.Key.ID,
UserName = x.Key.UserName,
BookType = x.Select(z => z.BookType).Distinct().Count(),
BookId = x.Select(z => z.BookId).Distinct().Count()
});
Related
I want to retrieve data by group two columns ( Parent_Id and Name ) using LINQ and get the result only the rows with the same group by values.
Child
---------
Id Parent_Id Name
1 1 c1
2 1 c2
3 2 c1 <-----
4 2 c1 <-----
5 3 c2
6 3 c3
7 4 c4 <-----
As you can see, for Parent_Id 1 and 2, Name are different. So, I don't what those rows.
The result I want is like
Parent_Id Name
2 c1
4 c4
What I have tried is
from c in Child
group c by new
{
c.Parent_Id,
c.Name
} into gcs
select new Child_Model()
{
Parent_Id = gcs.Key.Parent_Id,
Name= gcs.Key.Name
};
But it return all rows.
As you describe it you should group by Parent_id only and get the groups that have distinct Names:
var result = children
.GroupBy(c => c.Parent_Id)
.Where(g => g.Select(t => t.Name).Distinct().Count() == 1)
.Select(g => new
{
Parent_Id = g.Key,
Name = g.Select(c => c.Name).First()
});
Reduced to final edit as per Gert Arnold's request:
var result = from r in (from c in children
where !children.Any(cc => cc.Id != c.Id &&
cc.Parent_Id == c.Parent_Id &&
cc.Name != c.Name)
select new {
Parent_Id = c.Parent_Id,
Name = c.Name
}).Distinct().ToList()
select new Child_Model
{
Parent_Id = r.Parent_Id,
Name = r.Name
};
var myModel = Child.GroupBy( c => $"{c.Parent_Id}|{c.Name}",
(k, list) => new Child_Model{
Parent_Id = list.First().Parent_Id,
Name = list.First().Parent_Id,
Count = list.Count()})
.Max (cm => cm.Count);
You can add a condition to filter result (groupName.Count() > 1):
from c in childs
group c by new { c.Parent_Id, c.Name } into gcs
where gcs.Count() > 1
select new { gcs.Key.Parent_Id, gcs.Key.Name }
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 made up a test case:
I have a table like this
Id|IdA|IdW|Quantity
1 1 3 5
2 1 4 2
3 2 5 3
Id is the primary key, IdA is the article id, IdW is the box id, quantity is the amount of articles.
Now I have to group by IdA summing the quantities, so I'm doing:
var groups =
models
.GroupBy(x => new { x.IdA })
.Select
(
x =>
new Model
{
Id = (x.Select(y => y.Id).Count() > 1) ? 0 : x.Select(y => y.Id).First(),
IdA = x.Key.IdA,
Qty = x.Sum(y => y.Qty)
}
);
Here models is the table above. It works fine, I also managed to kept the primary key when no grouping is done (there is only one IdA)
Now I want to do this: I want to keep the IdW for the ones that haven't been grouped. The ideal result would be:
Id|IdA|IdW|Quantity
0 1 0 7
3 2 5 3
I tried to do a foreach on the groups, retrieving the row using the primary key, and then setting the IdW to the group, like this:
foreach(var e in groups)
{
var nonGroupedRow = models.Where(x => e.Id != 0 && x.Id == e.Id).FirstOrDefault();
var targetModel = groups.FirstOrDefault(x => x.Id == e.Id);
if(nonGroupedRow != null && targetModel != null)
{
targetModel.IdW = nonGroupedRow.IdW;
}
}
This incredibly is not working. Both groups still have IdW = 0. I also made up another test to be sure, doing:
void Main()
{
var a = new List<A> { new A { Id = 1 }, new A { Id = 2 } };
a.FirstOrDefault(x => x.Id == 1).Id = 2;
// both have Id = 2
}
class A
{
public long Id {get;set;}
}
It just have to work in my head, also given the example here above, yet it's not. Where am I wrong?
Firstly your count is counting the amount of entries found in the group by so you do not need to specify it to count the id's it would be the same
Secondly same thing to retrieve the first one's Id, take the first entry from the grouped data then the id property from there
You basically had the answer
var groups =
models
.GroupBy(x => new { x.IdA })
.Select
(
x =>
new Model
{
Id = (x.Count() > 1) ? 0 : x.First().Id,
IdA = x.Key.IdA,
IdW = (x.Count() > 1) ? 0 : x.First().IdW,
Qty = x.Sum(y => y.Qty)
}
);
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() }
);
My table data looks like:
table 1:
Id CId Message
1 1 E:MMM
1 1 E:NNN
1 1 E:OOO
1 2 E:PPP
1 2 E:PPP
table 2:
Id CId Message
1 1 W:NNN
1 1 W:OOO
After merging two tables using linq my output table should be like:
Result table:
Id CId ErMessage WrMessage
1 1 E:MMM*E:NNN*E:OOO W:NNN*W.OOO
1 2 E:PPP*E:PPP
Please help me how to achieve.
var q =
from t1 in
table1.GroupBy(g => g.ID).Select(g => new
{
ID = g.Key,
Message = string.Join("*", g.Select(v => v.Message).ToArray())
})
join
t2 in
table2.GroupBy(g => g.ID).Select(g => new
{
ID = g.Key,
Message = string.Join("*", g.Select(v => v.Message).ToArray())
}) on t1.ID equals t2.ID
select new
{
ID = t1.ID,
ErMessage = t1.Message,
WrMessage = t2.Message
};