distinct values in a Linq to sql string.Join() - c#

I have a table which contains the schedule for a class. it contains the teacherid and name, datetime of the class and the course for that specific time.
teacherid teachername startdate coursename
1 john 9/1/2014 10:00 math
2 john 9/2/2014 10:00 math
3 jane 9/3/2014 10:00 english
4 john 9/4/2014 10:00 french
5 jack 9/5/2014 10:00 history
6 jane 9/6/2014 10:00 math
I want to write a linq to sql query which returns which teacher gives which courses, as such:
Teachername courses
john math, french
jane english, math
jack history
I've gotten as far as the following
var _classes = from _c in dbContext.classes
where _c.StartDate < System.DateTime.Now
group _c by new
{
_c.TeacherId,
_c.TeacherName,
_c.CourseName
} into g
select new
{
g.Key.TeacherName,
courses = string.Join(",", from i in g select i.CourseName)
};
but i'm getting the following output
Teachername courses
john math, math, french
jane english, math
jack history
so john is getting the math value twice.
how do I make the string.Join function use distinct values?
thanks

There is no query syntax for distinct so you should change to method syntax:
courses = string.Join(",", g.Select(i => i.CourseName).Distinct())

Add Distinct to your select clause in String.Join like:
courses = string.Join(",", (from i in g select i.CourseName).Distinct())
Or use method Syntax for select as well like:
courses = string.Join(",", (g.Select(i=> i.CourseName).Distinct())

Related

Sort IQueryable by specific order

I have a table that I want to pull items by name in a certain order and by date.
id name date
1 XYZ 1:30
2 ABC 1:40
3 LMNOQ 1:50
4 ABC 1:20
I created the order
List<string> itemNames = new List<string>();
documentOrder.Add("XYZ");
documentOrder.Add("ABC");
documentOrder.Add("LMNOQ");
Then pulled the data, I think order will stay intact.
var myTable = _context.TheTable.Where(x => itemNames.Contains(x.id));
myTable data will look like
id name date
1 XYZ 1:30
2 ABC 1:40
4 ABC 1:20
3 LMNOQ 1:50
Now I need to sort by dates without messing up the name order. I need it look like this.
id name date
1 XYZ 1:30
2 ABC 1:20
4 ABC 1:40
3 LMNOQ 1:50
var myTable = _context.TheTable.Where(x => itemNames.Contains(x.id))
.OrderBy(x => x.name).ThenBy(x => x.date);
When using an IQueryable you can get it ordered as you want (by name, then by date... which looks a bit like a time) with multiple ordering statements.
var orderedQueryable = queryable.OrderBy(q => q.Name).ThenBy(q => q.Date);

LINQ group by on a single column

I have a database table that looks like this:
ID USERID DATE NAME
1 1 01-01-2001 aaaa
1 2 01-02-2001 aaaa
1 3 01-03-2001 aaaa
2 5 02-02-2002 bbbb
2 6 02-02-2002 bbbb
2 7 02-02-2002 bbbb
So I want to group everything by ID, so it has multiple USERIDs for each ID. However DATE and NAME are all the same. So how do get this as a linq query?
So far I thought of doing this, and this works for the users
from table in context.table
group table.USERID by table.ID into grp
orderby grp.Key descending
select new
{
ID = grp.Key,
Users = grp.ToList()
}
But this does not work if I add other items like DATE because DATE is sometimes different. However if it would select the first date that would be just fine.
EDIT what I would like as result is:
ID Users DATE NAME
1 1,2,3 01-01-2001 aaaa
2 5,6,7 02-02-2002 bbbb
You group by multiple columns:
from table in context.table
group new{table.UserID,table.Date} by new{table.ID,table.Name} into grp
orderby grp.Key.ID descending
select new
{
ID = grp.Key.ID,
Date=grp.FirstOrDefault().Date,
Name=grp.Key.Name,
Users = grp.Select(e=>e.UserID).ToList()
}

using distinct in DataTable.Select function

I have a data table and I want to populate two extra datatables using this datatable,here is a simple form of my table
My data table columns are
[name][family][id][propertyid][propertyEnergy]
John smith 1 12 Gas
John smith 1 13 Gas
John smith 1 14 null
John smith 1 15 Gas
Hannah smith 2 16 Gas
Hannah smith 2 17 Gas
Hannah smith 2 18 Gas
I want to use this query in datatable select distinct [name][family][id] from table
which results
John smith 1
Hannah smith 2
and again I use this query in another datatable select [id][propertyid][propertyEnergy] from table which results
1 12 Gas
1 13 Gas
1 14 null
1 15 Gas
2 16 Gas
2 17 Gas
2 18 Gas
I searched and found that I can DataTable.Select but examples that I have seen shows that I can only add Where sentense to DataTable.Select and I have no idea how to perform things like Distinct in it,
Can you please help me or give me some hints how to do it?
Thank you so much
I'd use Linq-To-DataTable instead:
var distinctNames = table.AsEnumerable()
.Select(row => new
{
Name = row.Field<string>("Name"),
Family = row.Field<string>("Family"),
ID = row.Field<int>("ID")
})
.Distinct();
var distinctProperties = table.AsEnumerable()
.Select(row => new
{
ID = row.Field<int>("ID"),
PropertyID = row.Field<int>("PropertyID"),
PropertyEnergy = row.Field<int>("PropertyEnergy")
})
.Distinct();
If you need two additional DataTables you have to create and fill them manually since the columns are different than the main-table. You can fill them in a loop from the queries above.
This should work as it is:
string[] nameColumns = { "Name", "Family", "ID" };
DataTable tblNames = table.Clone();
var removeColumns = tblNames.Columns.Cast<DataColumn>()
.Where(c => !nameColumns.Contains(c.ColumnName)).ToList();
removeColumns.ForEach(c => tblNames.Columns.Remove(c));
foreach (var x in distinctNames)
tblNames.Rows.Add(x.Name, x.Family, x.ID);
string[] propertyColumns = { "ID", "PropertyID", "PropertyEnergy" };
DataTable tblProperties = table.Clone();
removeColumns = tblProperties.Columns.Cast<DataColumn>()
.Where(c => !propertyColumns.Contains(c.ColumnName)).ToList();
removeColumns.ForEach(c => tblProperties.Columns.Remove(c));
foreach (var x in distinctProperties)
tblProperties.Rows.Add(x.ID, x.PropertyID, x.PropertyEnergy);

C# - How to find most frequent date from list

I seem to have drawn a blank. I have a list of sales, retrieved like so:
List<Sales> sales = ctn.Sales.Where(s => s.DateSold >= request.FromDate && s.DateSold <= request.ToDate).ToList();
An item in the list of sales would look something like the following:
SaleID | DateSold | ProductID | ShopID
As part of a report, I would like to return to the user a simple string informing them of what day is the day that tends to sell the most.
So I think what I should do is group sales by day, get a count for each day, and then evaluate which has the highest number, however I'm not sure exactly how to do this.
Can anyone help?
You just have to group on the DateSold and then order by the count (which tells you how many items belong to the group):
salesByDay = sales.GroupBy(s => s.DateSold).OrderBy(g => g.Count());
If you set the exact DateTime of sold item into DateSold, you probably want to take Date part and group by it
from sale in sales
group sale by sale.DateSold.Date into grouped
orderby grouped.Count()
select new {Date = grouped.Key, Count = grouped.Count()};
This will provide you the date with the most sales:
sales.GroupBy(x => x.DateSold).OrderByDescending(g => g.Count()).FirstOrDefault().Key;

Latest records of each type?

I have two tables in my entity data model (converted from an old database)
Entity1: Food_I_Have_In_Fridge:
Food | Category
---------------
Apple | Fruit
Beef | Meat
Tomato| Veggie
Pork | Meat
Bacon | Meat
Orange| Fruit
Carrot| Veggie
Entity2: Food_I_ate:
Date | Food
------------
01/01| Apple
01/01| Beef
01/02| Pork
01/03| Orange
01/04| Tomato
I want to generate a list of last things I ate categorized by the food category. The output looks like:
Categ| Food
-----------
Meat | Pork
Fruit| Orange
Veggi| Tomato
I have the equivalent sql code below, but because we are ditching sql completely, I am trying to achieve the following with entity framework.
with FW as (
select a.[Date], f.category, a.food, a.date
from
[Food_I_ate] a
inner join
[Food_I_Have_In_Fridge] f on a.Food = f.Food
)
select
FW2.category,
FW2.Food,
FW2.Date
from
(select FW.category, max(fw.ix) as maxix
from FW group by FW.category) FW
inner join
FW FW2 on FW2.ix = FW.maxix and FW2.category = FW.category
I was wondering how to achieve this using entity framework?
Try this, assuming your entities are db.FoodIAte and db.FoodInFridge (loving the table names!):
var food = (from fif in db.FoodInFridge
join fia in db.FoodIAte on fif.Food equals fia.Food
select new
{
Food = fif.Food,
Category = fif.Category,
Date = fia.Date
})
.OrderByDescending(f => f.Date)
.ToList()
That way you have the food in order of date eaten, most recent first. Then if you want the top three of them, you can do (make sure you check that the food list is longer/same size as the number you are taking though, otherwise it'll die!):
var topFood = food.Take(3).ToList();

Categories