DistinctBy With Condition in LINQ - entity-framework

I am having entity collection from Database which contains certain duplicates like One sequence with values and other sequence with empty values. I would like to remove sequence with empty one. I have tired moreLINQ for DistinctBy but still my case is not satisfying.
I have a following list from result set.
Result: Id=1, Name="Test1", Status="New", Values=NULL
Result: Id=1, Name="Test1", Status="Assigned", Values=123
Result: Id=2, Name="Test2", Status="New", Values=NULL
Result: Id=2, Name="Test2", Status="Assigned", Values=698
Result: Id=3, Name="Test3", Status="Assigned", Values=569
Result: Id=4, Name="Test4", Status="New", Values=NULL
Result: Id=5, Name="Test5", Status="Assigned", Values=156
I would like to retrieve follwoing outputs always by skipping duplicate with empty values or New status.
Result: Id=1, Name="Test1", Status="Assigned", Values=123
Result: Id=2, Name="Test2", Status="Assigned", Values=698
Result: Id=3, Name="Test3", Status="Assigned", Values=569
Result: Id=4, Name="Test4", Status="New", Values=NULL
Result: Id=5, Name="Test5", Status="Assigned", Values=156

Group by Id and take the first record of each group that is ordered by Status:
var records = new[]
{
(Id:1, Name:"Test1", Status:"New", Values:default(int?)),
(Id:1, Name:"Test1", Status:"Assigned", Values:123),
(Id:2, Name:"Test2", Status:"New", Values:default(int?)),
(Id:2, Name:"Test2", Status:"Assigned", Values:698),
(Id:3, Name:"Test3", Status:"Assigned", Values:569),
(Id:4, Name:"Test4", Status:"New", Values:default(int?)),
(Id:5, Name:"Test5", Status:"Assigned", Values:156),
};
var result = records
.GroupBy(r => r.Id)
.Select(r => r.OrderBy(x => x.Status).First());
Result:
Id Name Status Values
------------------------------
1 Test1 Assigned 123
2 Test2 Assigned 698
3 Test3 Assigned 569
4 Test4 New null
5 Test5 Assigned 156

You can so something like below
DOTNETFIDDLE working code
var modified = listOfValues
.GroupBy(x => x.Id)
.Select(x => x.OrderByDescending(x => x.Values ?? int.MinValue).FirstOrDefault());
Results:

Related

How to return a default msg when there's no json key value

I am running the following query:
select id, products::jsonb ->'price_p' -> 'value' as total_price from tb
But sometimes the record dont't have price_p key in the jsonb column. How can I return a msg like no price_p key found when there is no price_p in the json?
employee_nps": {"value": ["7"]}
example:
id products
1 {"price_p":{"value": ["10"]}}
2 {"net_price":{"value":["12.30"]}}
would return:
1 10
2 "no price_p"
Postgres 14

Easiest way to delete all records except the last 10 by date using EFCore [duplicate]

Let's say that I have a table like:
Id Name Category CreatedDate
1 test test 10-10-2015
2 test1 test1 10-10-2015
...
Now, I would like to delete all rows and leave only the top 10 from all categories (by top 10 I mean the 10 newest according to createdDate).
Using raw SQL, it would be like:
DELETE FROM [Product]
WHERE id NOT IN
(
SELECT id FROM
(
SELECT id, RANK() OVER(PARTITION BY Category ORDER BY createdDate DESC) num
FROM [Product]
) X
WHERE num <= 10
How is this done when using the DbContext in Entity Framework?
// GET all products
var list = ctx.Products.ToList();
// GROUP by category, ORDER by date descending, SKIP 10 rows by category
var groupByListToRemove = list.GroupBy(x => x.Category)
.Select(x => x.OrderByDescending(y => y.CreatedDate)
.Skip(10).ToList());
// SELECT all data to remove
var listToRemove = groupByListToRemove.SelectMany(x => x);
// Have fun!
ctx.Products.RemoveRange(listToRemove);
Guessing it will take a whil if you have a lot of data but.
var oldItems = efContext.Products
.GroupBy(x => x.Category,
(c,p) => p.OrderByDescending(x => p.createdDate).Skip(10))
.SelectMany(p => p);
efContext.Products.RemoveRange(oldItems);
Will do the trick
(Written in notepad)

Is there a way to use `COUNT(DISTINCT)` in EF Core 3.1?

I have a table with the following data
ID DateColumn Amount
1 2021-01-25 50
2 2021-01-24 10
1 2021-01-25 100
I need the following output,
ID DayCount TotalAmount
1 1 150
2 1 10
I'm trying to lambda expression that would generate the following SQL query,
select ID, Count(distinct DateColumn) as DayCount, Sum(Amount) as TotalAmount
from test
group by id
I've writte the following expression,
return await _context.Tests
.GroupBy(g => g.id)
.Select(s => new
{
Data = s.Key,
Count = s.Select(t => t.DateColumn).Distinct().Count()
}).ToListAsync();
and it throws the InValidOperation exception.
There seems to be an error in the resulting table for the first record, which should have a value of 2 for the DayCount.
The resting table construction looks like it could use some rearchitecting due to the Id column containing duplicates.
Regardless of structure, you can use an inner GROUP BY to achieve similar results:
return await _context.Tests
.GroupBy(g => g.id)
.Select(s => new
{
Data = s.Key,
Count = s.GroupBy(t => t.DateColumn).Select(g => g.key).Count()
})
.ToListAsync();

Using group in Entity Framework to return model and count

I have some data, similar to this
Email Date Id
Anne 1/1/00 1
Anne 1/2/00 2
Anne 1/4/00 3
Bert 1/4/00 4
Bert 1/5/00 5
I'm trying to return the following 2 results from the above into something like
List<Model, Count>
Where Model is a class with Email and Date (most recent Date) properties, and count is the total count
var m = (from e in emailOpens
group e by e.EmailAddress into g
select new
{
Model = g.Key,
Occurance = g.Count()
}).ToList();
The issue is, the above will return only the email addresses but I change the group statement to
group e by e into g
Then naturally there is nothing to count, so my Occurrence property remains at 0
What am I missing here?
You are missing just one statement:
var m = (from e in emailOpens
group e by e.EmailAddress into g
select new
{
Model = new
{
Email = g.Key,
// Select maximum date from group
MostRecentDate = g.Max(m => m.Date)
},
Occurance = g.Count()
}).ToList();

search the word in linq to sql?

Table users:
userid username
------------------------------------
1 venkatesh duggirala
2 deviprasad
3 dhanu
if user sends username="d" then need to get all records.by using "contains" i am getting 2,3 as result.but 1st record also having "d" in duggirala.
query:
var result = from p in cxt.users
where p.Users.username.Contains(name)
select new
{
p.Userid
};
rewrite your query like this:
var result = from p in cxt.users
where p.Users.username.ToLower().Contains(name.ToLower())
select new
{
p.Userid
};