EF for Top 10 most popular locations c# [closed] - c#

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 3 years ago.
Improve this question
I have a table tbLocations with the following columns:
int id {PRIMARY_KEY, AUTO_INCREMENT}
int userid {Foreign key with table_users}
varchar(200) location
In this table I have the following rows:
1, 1, New York
2, 1, California
3, 1, Seattle
4, 1, New York
5, 2, Seattle
6, 2, Ontario
7, 3, Chicago
8, 4, Las Vegas
9, 5, New York
I want to create a c# linq query that gets me the top 10 locations, in my case I should get
New York 2
Seattle 2
The issue here is that a location can be duplicate for a user i.e. New York is duplicate for userid 1 so I don't want such duplication to affect the final report.
Like in the final report I have New York =2 and not =3
How can I do this in LINQ?
I really have no idea where to start, I tried by grouping by but that didn't work

Start with this query:
select top 10 count(*) cnt, [location] from
(
select count(*) as dupl, userid, [location]
from tbLocations
group by userid, [location]
) as test
group by [location]
order by cnt desc
This gives these results:
cnt location
2 New York
2 Seattle
1 Ontario
1 California
1 Chicago
1 Las Vegas

Here is my solution:
var locations = new List<Location>
{
new Location{ Id = 1, UserId = 1, Name = "New York" },
new Location{ Id = 2, UserId = 1, Name = "California" },
new Location{ Id = 3, UserId = 1, Name = "Seattle" },
new Location{ Id = 4, UserId = 1, Name = "New York" },
new Location{ Id = 5, UserId = 2, Name = "Seattle" },
new Location{ Id = 6, UserId = 2, Name = "Ontario" },
new Location{ Id = 7, UserId = 3, Name = "Chicago" },
new Location{ Id = 8, UserId = 4, Name = "Las Vegas" },
new Location{ Id = 9, UserId = 5, Name = "New York" },
};
var topLocations = locations
.GroupBy(location => new { location.UserId, location.Name })
.Select(group => group.First())
.GroupBy(location => location.Name)
.Select(group => new { group.Key, Count = group.Count() })
.OrderByDescending(location => location.Count)
.Take(2);
foreach (var item in topLocations)
{
Console.WriteLine($"{item.Key} {item.Count}");
}

Related

Select TOP 1 for each FK in list using Entity Framework

I have a large table where I'm trying to select the top 1 row for each FK in a list.
My table is laid out as:
ChangeId | AssetId | Timestamp
1 1 123
2 2 999
3 1 3478
4 3 344
5 2 1092
Where ChangeId is my PK, AssetId is my FK and Timestamp is the value I'm trying to select.
If I try the following:
var results =
from Asset in _context.Asset
join change in _context.Change on Asset.AssetId equals change.AssetId into potentialChange
from actualChange in potentialChange.OrderByDescending(y => y.ChangeId).Take(1)
select
{
AssetId,
Timestamp
}
Where my expected result would be:
[
{
AssetId: 1,
Timestamp: 3478
},
{
AssetId: 2,
Timestamp: 1092
},
{
AssetId: 3,
Timestamp: 344
}
]
This query flags up the The LINQ expression could not be translated and will be evaluated locally. which is not suitable for a production rollout.
Running a foreach loop and selecting each item out 1 by 1 works, not it's not a performant solution.
Is there a suitable way to achieve the above?
Try to group it by AssetId and take max from each group
var results =
from Asset in _context.Asset
join change in _context.Change on Asset.AssetId equals change.AssetId into potentialChange
group potentialChange by potentialCharge.AssetId into g
select
{
g.Key,
g.Max().Timestamp
}
Use Group By as follows:
List<MyTable> data = new List<MyTable>()
{
new MyTable(){ChangeId = 1, AssetId = 1, Timestamp = 123},
new MyTable(){ChangeId = 2, AssetId = 2, Timestamp = 999},
new MyTable(){ChangeId = 3, AssetId = 1, Timestamp = 123},
new MyTable(){ChangeId = 5, AssetId = 3, Timestamp = 123},
new MyTable(){ChangeId = 5, AssetId = 2, Timestamp = 123},
};
var expectedData = data.OrderByDescending(d => d.Timestamp).GroupBy(d => d.AssetId).Select(g => new
{
AssetId = g.Key,
TimeStamp = g.First().Timestamp
}).ToList();
This will give your expected result.
Try using .First() instead of .Take(1)
LINQ How to take one record and skip rest c#

Linq to select objects with unique Id and greatest date?

I have a list of objects that look like this:
public class A
{
public int Id {get; set;}
public DateTime Date {get;set;}
public int TypeId {get; set;}
public int Version {get; set;}
}
My data looks like this:
Id Date TypeId Version
1 10/3/18 1 1
2 10/3/18 1 2
3 10/4/18 1 1
4 10/4/18 2 1
How can I make a linq query to return these 2 in a list where it gets the item with the greatest date where the version # is 1 and also uses the TypeId to return more items?
Id Date TypeId Version
3 10/4/18 1 1
4 10/4/18 2 1
This is what I have tried but my code only returns one item because of my FirstOrDefault function.
var q = from n in A.All.Where(x => x.Version == 1)
group n by n.TypeId into g
select g.OrderByDescending(t => t.Date).FirstOrDefault();
You need to group by typeId and then in each group order elements by date. Then you can pick first element in each group. Try this code:
var input = new[]
{
new A {Id = 1, Date = new DateTime(2018, 10, 3), TypeId = 1, Version = 1},
new A {Id = 2, Date = new DateTime(2018, 10, 3), TypeId = 1, Version = 2},
new A {Id = 3, Date = new DateTime(2018, 10, 4), TypeId = 1, Version = 1},
new A {Id = 4, Date = new DateTime(2018, 10, 4), TypeId = 2, Version = 1},
};
var result = input.Where(a => a.Version == 1)
.GroupBy(a => a.TypeId)
.Select(g => g.OrderByDescending(x => x.Date).First())
.ToArray();

How to re change sorting of the coming result manually .cs

Hi I have a code as below and for more detail I am placing an image as below . I want my coming result record be re-change like my 2 and 4 result should be display at last of my product list(DataList).
I am not able to excess the code so need to re-arrange from .cs page. Any idea
ProductList.DataSource = ProductDataSource.NarrowSearch(_Keywords, this.CategoryId, _ManufacturerId, 1, 0, _PageSize, (_HiddenPageIndex * _PageSize), SortResults.SelectedValue);
ProductList.DataBind();
So I actually want my data to be displayed as [0], [1], ... [9], [10], [2], [4]
Answer resolved as
List<Product> narrowsearch = new List<Product>();
List<Product> narrowsearchstoredata = new List<Product>();
narrowsearchstoredata = ProductDataSource.NarrowSearch(_Keywords, this.CategoryId, _ManufacturerId, 1, 0, _PageSize, (_HiddenPageIndex * _PageSize), SortResults.SelectedValue);
Product item1 = narrowsearchstoredata[0];
Product item2 = narrowsearchstoredata[3];
narrowsearchstoredata.Remove(item1);
narrowsearchstoredata.Remove(item2);
narrowsearchstoredata.Add(item1);
narrowsearchstoredata.Add(item2);
ProductList.DataSource = narrowsearchstoredata;
ProductList.DataBind();
Just remove the items at the indices and add them later.
List<Department> departmentList = new List<Department>();
departmentList.Add(new Department { ID = 1, Description = "HR" });
departmentList.Add(new Department { ID = 2, Description = "IT" });
departmentList.Add(new Department { ID = 3, Description = "Sales" });
departmentList.Add(new Department { ID = 4, Description = "Accounting" });
departmentList.Add(new Department { ID = 5, Description = "Marketing" });
departmentList.Add(new Department { ID = 6, Description = "Fun" });
departmentList.Add(new Department { ID = 7, Description = "Games" });
departmentList.Add(new Department { ID = 8, Description = "Awesome" });
departmentList.Add(new Department { ID = 9, Description = "Confusing" });
Department item4 = departmentList[3];
Department item6 = departmentList[5];
departmentList.Remove(item4);
departmentList.Remove(item6);
departmentList.Add(item4);
departmentList.Add(item6);
And then bind the control.

LINQ to Entities - Where Muliple And clause in query [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 9 years ago.
Improve this question
I want to retrieve all records of manufacturer in LINQ using a many-to-many join.
Lets consider
Table 'Item':
id | name
----------
1 | A
---------
2 | B
--------
3 | C
--------
Table 'Manufacturer':
ManufactuerId | Name
-------------------
1 | XYZ
-------------------
2 | ABC
--------------------
3 | ZZZ
----------------------
Table 'ManufacturerItem':
ManufacturerItemID | ManufacturerId | ItemId
-------------------------------------------
1 | 1 | 1
-------------------------------------------
2 | 1 | 2
-------------------------------------------
3 | 2 | 1
------------------------------------------
4 | 3 | 2
------------------------------------------
5 | 1 | 3
------------------------------------------
I would like to fetch the records of a manufacturer(s) who has all the items that I have supplied in.
So, given an input of {A, B} I would like to get an output of XYZ Manufacturer.
var tableItems = new[] {
new { Id = 1, Name = "A" },
new { Id = 2, Name = "B" },
new { Id = 3, Name = "C" }
};
var tableManufacturer = new[] {
new { ManufacturerId = 1, Name = "XYZ" },
new { ManufacturerId = 2, Name = "ABC" },
new { ManufacturerId = 3, Name = "ZZZ" }
};
var tableManufacturerItem = new[]
{
new {ManufacturerItemID = 1, ManufacturerId = 1, ItemId = 1},
new {ManufacturerItemID = 2, ManufacturerId = 1, ItemId = 2},
new {ManufacturerItemID = 3, ManufacturerId = 2, ItemId = 1},
new {ManufacturerItemID = 4, ManufacturerId = 3, ItemId = 2},
new {ManufacturerItemID = 5, ManufacturerId = 1, ItemId = 3},
};
var itemsToSearch = new[] { "A", "B" };
var result = tableManufacturerItem
.GroupBy(x => x.ManufacturerId)
.Where(m => tableItems.Where(item => itemsToSearch.Contains(item.Name)).Select(x => x.Id)
.Except(m.Select(x => x.ItemId))
.Count() == 0)
.Select(x => tableManufacturer.First(m => m.ManufacturerId == x.Key))
.Select(m => m.Name)
.ToList();

LINQ - Can't add column to result without changing multi-table grouping

Suppose I have a "database" defined as:
// Baked goods vendors
var vendor = new[] {
new { ID = 1, Baker = "Pies R Us", StMnemon = "NY", Items = 8, Rating = 9 },
new { ID = 2, Baker = "Mikes Muffins", StMnemon = "CA", Items = 5, Rating = 9 },
new { ID = 3, Baker = "Best Bakers", StMnemon = "FL", Items = 2, Rating = 5 },
new { ID = 4, Baker = "Marys Baked Treats", StMnemon = "NY", Items = 8, Rating = 7 },
new { ID = 5, Baker = "Cool Cakes", StMnemon = "NY", Items = 4, Rating = 9 },
new { ID = 6, Baker = "Pie Heaven", StMnemon = "CA", Items = 12, Rating = 9 },
new { ID = 7, Baker = "Cakes N More", StMnemon = "GA", Items = 6, Rating = 8 },
new { ID = 8, Baker = "Dream Desserts", StMnemon = "FL", Items = 2, Rating = 7 }
};
// Locations
var location = new[] {
new {ID= 1, State = "New York", Mnemonic = "NY"},
new {ID= 2, State = "Massachusetts", Mnemonic = "MA"},
new {ID= 3, State = "Ohio", Mnemonic = "OH"},
new {ID= 4, State = "California", Mnemonic = "CA"},
new {ID= 5, State = "Florida", Mnemonic = "FL"},
new {ID= 6, State = "Texas", Mnemonic = "TX"},
new {ID= 7, State = "Georgia", Mnemonic = "GA" }
};
I want to build a query that would be the equivalent of the SQL query:
SELECT State, Rating, SUM(Items) AS 'Kinds'
FROM vendor, location
WHERE vendor.StMnemon = location.Mnemonic
GROUP BY State, Rating
Two things of interest in this query are:
The GROUP BY involves multiple tables, and
The result contains a summation of a column not appearing in the grouping criteria.
I've seen the solutions in the posts on grouping by multiple tables and summing columns not in the group-by. The problem is that combining both doesn't really duplicate the relational query.
I try to duplicate it in LINQ with the following code:
var query = from v in vendor
join l in location
on v.StMnemon equals l.Mnemonic
orderby v.Rating ascending, l.State
select new { v, l };
var result = from q in query
group q by new {
s = q.l.State,
r = q.v.Rating
/* ==> */ , i = q.v.Items
} into grp
select new
{
State = grp.Key.s,
Rating = grp.Key.r
/* ==> */ , Kinds = grp.Sum(k => grp.Key.i)
};
This results in:
=================================
State Rating Kinds
Florida 5 2
Florida 7 2
New York 7 8
Georgia 8 6
California 9 5
California 9 12
New York 9 8
New York 9 4
=================================
Whereas, the SQL query given above gives this result:
=========================
State Rating Kinds
Florida 5 2
Florida 7 2
New York 7 8
Georgia 8 6
California 9 17
New York 9 12
=========================
The discrepancy is because there seems to be no place to put additional columns, other than in the grouping criteria, which of course changes the grouped result. Commenting out the two lines indicated by the /* ==> */ comment in the code above will give the same grouping as the SQL result, but of course that removes the summation field that I want to include.
How do we group multiple tables in LINQ and include additional criteria without changing the grouped result?
something like this seems to return the same as the SQL query:
var result = from v in vendor
from l in location
where l.Mnemonic == v.StMnemon
group v by new { l.State, v.Rating } into grp
orderby grp.Key.Rating ascending, grp.Key.State
select new {State = grp.Key.State, Rating = grp.Key.Rating, Kinds = grp.Sum(p=>p.Items)};
foreach (var item in result)
Console.WriteLine("{0}\t{1}\t{2}", item.State, item.Rating, item.Kinds);
You can do an aggregation outside of the group:
var query = from v in vendor
join l in location
on v.StMnemon equals l.Mnemonic
orderby v.Rating ascending, l.State
select new { v, l };
var result = from q in query
group q by new {
s = q.l.State,
r = q.v.Rating
} into grp
select new
{
State = grp.Key.s,
Rating = grp.Key.r,
Kinds = grp.Sum(g => g.Items)
};
Grouping is a little tricky to grasp - it returns an IGrouping that has one property - Key. The actual items in that grouping are returned by the GetEnumerator() function that lets you treat the group as a collection of those items, meaning you can do aggregation on the items within that group.

Categories