I've got the following data
title | useful
ttitle1 | Yes
ttitle1 | Yes
ttitle1 | No
ttitle2 | Yes
I would like to group the above data and flatten it so I get the following result:
Title | Useful Count | Not Useful Count
tttitle1 | 2 | 1
tttitle2 | 1 | 0
Tried this, but it does not produce the correct result:
var query = (from r in ratings
group r by new { r.ArticleTitle, r.Useful } into results
group results by new { results.Key.ArticleTitle } into results2
from result in results2
select new
{
Title = result.Key.ArticleTitle,
Yes = result.Select(i => i.Useful).Count(),
No = result.Select(i => i.Useful == false).Count()
});
Any help?
It seems to me that the only problem is that you're grouping twice. I'd expect this to work:
var query = from rating in ratings
group rating by rating.ArticleTitle into g
select new
{
Title = g.Key,
Yes = g.Count(r => r.Useful),
No = g.Count(r => !r.Useful)
};
Or not in query expression form:
var query = ratings.GroupBy(r => r.ArticleTitle,
(key, rs) => new
{
Title = key,
Yes = rs.Count(r => r.Useful),
No = rs.Count(r => !r.Useful)
});
You don't need to group twice to get the desired result. One Grouping would be fine:
var query = (from r in ratings
group r by new { r.ArticleTitle } into g
from result in groups
select new
{
Title = result.Key,
Yes = result.Select(i => i.Useful).Count(),
No = result.Select(i => !i.Useful).Count()
});
Related
I want to get the count of each items in columns using LINQ GroupBy, however I don't get the expected output.
Example :
NAME | Items | Items2
1.ken | asd | zxc
2.kent | null | zwe
3.ken | qwe | null
Expected output:
NAME | Items | Items2
ken | 2 | 1
kent | 0 | 1
Code:
var Data = Items.GroupBy(z => z.Name)
.Select(s =>
new {
Name = s.Key,
Items = s.Count(q => q.Items),
Items2 = s.Count(x => x.Items2)
})
.ToList();
The above code does not work.
I think the null values create issues in Count() in the expected output. So I suggest you to add a condition in Count() to exclude null values. So your query will look like:
var Data = Items.GroupBy(z => z.Name)
.Select(s =>
new
{
Name = s.Key,
Items = s.Count(q => q.Items != null),
Items2 = s.Count(x => x.Items2 != null)
})
.ToList();
I want to get last user updated with a linq lambda expression using group by and the count of the remaining users. I don't know how I can do that.
here is my data :
userid | name | datetime | isdelete
1 | abc | 16-03-2017 15:45:59 | 0
1 | abc | 16-03-2017 12:45:10 | 0
2 | xyz | 16-03-2017 15:45:59 | 0
1 | abc | 16-03-2017 10:40:59 | 0
I want the result to look like this:
userid | name | datetime | count
1 | abc | 16-03-2017 15:45:59 | 3
2 | xyz | 16-03-2017 15:45:59 | 1
Here the count for userid = 1 should be 3 as there are three records for that id in the table.
I have written this query, but it is getting all the records.
List<Users> UList = new List<Users>();
UList = db.Users.Where(a => a.isdelete == false)
.OrderByDescending(a => a.datetime)
.Skip(skip)
.Take(pageSize)
.ToList();
Anyone know how I can get the data I want? Please let me know using linq lambda expression.
You need to group by user, than sort each group and take first from each group
var UList = (db.Users
.Where(a => a.isdelete == false)
.GroupBy(a => a.UserId)
.Select(g => new MyNewClass
{
Count = g.Count(),
User = g.OrderByDescending(a => a.datetime).First()
}
))
.Skip(skip)
.Take(pageSize)
.ToList();
You forgot to group your data:
var result = db.Users.Where(a => !a.isdelete)
.GroupBy(x => x.userid)
.Select(x => new User
{
userid = x.Key,
name = x.Last().Name,
datetime = x.OrderByDescending(a => a.datetime).First().datetime,
count = x.Count()
});
EDIT: This might be not optimal considering the performance as the call to Last and OrderByAscending will both iterate the whole data. To overcome this a bit you may re-structure this query a bit:
var result = db.Users.Where(a => !a.isdelete)
.GroupBy(x => x.userid)
.Select(x => new
{
user = x.OrderByDescending(a => a.datetime).First(),
count = x.Count()
})
.Select(x => new User {
name = x.user.name,
userid = x.user.userid,
datetime = x.user.datetime,
count = x.count
});
I have a datatable with 2 columns:
GuitarBrand | Status
---------------------
Fender | Sold
Fender | In Stock
Gibson | In Stock
Gibson | In Stock
I want to write a linq query to output
GuitarBrand | PercentSold | Sold/Total
---------------------------------------
Fender | 50% | 1/2
Gibson | 100% | 2/2
Here's what I have so far:
var groupedtable = from b in table.AsEnumerable()
group b by b.Field<"GuitarBrand"> into g
select new ( GuitarBrand = g.Key, Perecent = (float)g.Count()/(float)g.key)
Which I got from another post but it isn't even close to working, I get a Cannot Convert string to float. I've tried looking at other posts but I can't find anything.
Thanks!
You can use the following (hopefully self explanatory) query:
var groupedtable =
from b in table.AsEnumerable()
group b by b.Field<string>("GuitarBrand") into g
let Total = g.Count()
let Sold = g.Count(e => e.Field<string>("Status") == "Sold")
let SoldPercent = (float)Sold / (float)Total
select new
{
GuitarBrand = g.Key,
PercentSold = SoldPercent.ToString("p"),
TotalSold = Sold + "/" + Total
};
maybe something like this!
var groupedtable = from b in table.AsEnumerable()
group b by b.Field<"GuitarBrand"> into g
select new {
GuitarBrand = g.Key,
Perecent = g.Count(x=>x.Status.Eguals("Sold")/(float)g.Count()
}
Something like this should get you started. In your question, your output table is contradicting. I've assumed you want the data as labeled.
public static void Main()
{
var guitars = new List<Guitar>()
{
new Guitar(){ Brand = "Fender", Status = Status.Sold },
new Guitar(){ Brand = "Fender", Status = Status.InStock },
new Guitar(){ Brand = "Gibson", Status = Status.InStock },
new Guitar(){ Brand = "Gibson", Status = Status.InStock }
};
var query = guitars
.GroupBy(guitar => guitar.Brand)
.Select(group => new
{
GuitarBrand = group.Key,
Sold = group.Where(guitar => guitar.Status == Status.Sold).Count(),
Total = group.Count()
})
.Select(_ => new
{
_.GuitarBrand,
PercentSold = ((decimal)_.Sold / (decimal)_.Total) * 100,
SoldAndTotal = string.Format("{0}/{1}", _.Sold, _.Total)
});
}
class Guitar {
public string Brand { get; set; }
public Status Status { get; set; }
}
enum Status {
Sold,
InStock
}
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 have list of simple objects:
var r = new List
{
new { Id = 1, Value = 2, DateTime = DateTime.Parse("10.10.2014")},
new { Id = 2, Value = 3, DateTime = DateTime.Parse("10.10.2014")},
new { Id = 3, Value = 4, DateTime = DateTime.Parse("10.10.2014")},
new { Id = 1, Value = 5, DateTime = DateTime.Parse("11.10.2014")},
new { Id = 2, Value = 6, DateTime = DateTime.Parse("11.10.2014")}
};
I want to get object like:
DateTime | 1 | 2 | 3 |
10.10.2014 | 2 | 3 | 4 |
11.10.2014 | 5 | 6 | |
Is there any nice linq query to this? Smth like pivot/unpivot in sql maybe?
Try this:
r.ToLookup(t => t.id, t=>t.DateTime)
And if that doesn't work, read through this
You are looking to group the list according to id and then key the resulting list by dictionary. You should be able to do that with some combination of GroupBy, which creates a list of grouped lists and ToDictionary(), which creates allows you to specify a property of the object as a key and creates a dictionary from it.
You're looking for a simple GroupBy:
var result = r.GroupBy(x => x.DateTime)
.Select (grp => new
{
DateTime = grp.Key,
_1 = grp.Where(x => x.Id == 1).Select(x => x.Value).Cast<Int32?>().FirstOrDefault(),
_2 = grp.Where(x => x.Id == 2).Select(x => x.Value).Cast<Int32?>().FirstOrDefault(),
_3 = grp.Where(x => x.Id == 3).Select(x => x.Value).Cast<Int32?>().FirstOrDefault()
});
result is now:
If the number of Ids are not known at compile-time then there is no way to create a link statement to capture those Ids as new fields. Linq just can do that. The best you can do in that case is this:
var ids = r.Select(x => x.Id).Distinct().OrderBy(x => x).ToArray();
var query =
from x in r
group x by x.DateTime into gxs
let lookup = gxs.ToLookup(x => x.Id, x => (int?)x.Value)
select new
{
DateTime = gxs.Key,
Values = ids.Select(i => new
{
Id = i,
Value = lookup[i].FirstOrDefault(),
}).ToArray(),
};
That produces this:
If the Ids are known then the following variation is the best:
var query =
from x in r
group x by x.DateTime into gxs
let lookup = gxs.ToLookup(x => x.Id, x => (int?)x.Value)
select new
{
DateTime = gxs.Key,
_1 = lookup[1].FirstOrDefault(),
_2 = lookup[2].FirstOrDefault(),
_3 = lookup[3].FirstOrDefault(),
};