SELECT UNTIL in SQL with Entity Framework - c#

I would like to select rows until I found a certain Id which is numeric. If my data is ordered by Id the problem can be solved quite easy.
Id Name
-----------
1 Bob
2 Eve
3 Alice
4 Michael
5 Anne
6 Mike
To get all items until Id 4 is found the following SQL statement is sufficient:
SELECT * FROM Users WHERE Id <= 4
If the data is ordered by Name and I still would like to get the items until Id 4 is found I couldn't come up with a good solution.
Id Name
-----------
3 Alice
5 Anne
1 Bob
2 Eve
4 Michael
6 Mike
The output of the statement to be defined should be:
Id Name
-----------
3 Alice
5 Anne
1 Bob
2 Eve
4 Michael
EDIT 1:
With the following statement the output is almost what I need but missing the item with Id 4.
queryable.OrderBy(o => o.Name).TakeWhile(o => o.Id != 4);
Id Name
-----------
3 Alice
5 Anne
1 Bob
2 Eve
Is it possible to include the item with Id 4 too?
EDIT 2:
For now I'm going with this approach:
queryable.OrderBy(o => o.Name).TakeWhile(o => o.Id != 4).Union(queryable.Where(o => o.Id == 4))
As the Id is unique there should be no problem with the UNION statement. But I'm not sure if this statement is the most effective one.

Context.Table.OrderBy(p => p.Name).TakeWhile(p => p.id != 4);

var result = Users.TakeWhile((u,i)=> i == 0 || Users.ElementAt(i-1).Id != 4);
Another approach:
var result = Users.TakeWhile(u=>u.Id!=4)
.Union(Users.SkipWhile(u=>u.Id!=4).Take(1));

var results = from n in names.TakeWhile( n => n.Id != 4)
.Union(names.Where(n => n.Id == 4)) select n;

Related

linq for records not having a value

I have table with values
Table Event
Id UserId EventId
===========================
1 1 1
2 1 2
3 1 3
4 2 2
Table Users
Id FirstName LastName
===========================
1 xx xx-last
2 ww ww-last
3 dd dd-last
4 qq qq-last
I want to have the list of users which forexample don't have EventId=1. in this case it would be
User 2,3,4
how can i make it with linq
Assuming that your User entity has an Events navigation property:
var usersWithoutEvent1 = dbContext.Users
.Where(u => u.Events.All(e => e.Id != 1))
.ToArrayAsync();

C# Linq using distinct with union

I have a table in db as :
Id Name Stream Version UId Tab Key Value CreatedOn CreatedBy
1 Name1 GOP 1 U1 Tab1 co 1 07/01/2018 S, Adam
2 Name1 GOP 1 U2 Tab1 co 1 07/03/2018 S, Adam
3 Name1 GOP 1 U3 Tab2 st 2 07/03/2018 S, Adam
4 Name1 GOP 2 OR Tab1 co 1 07/02/2018 P, Silver
5 Name2 GOP 1 OR Tab1 co 1 07/02/2018 P, Silver
6 Name3 GOP 0 OR1 Tab0 coe 1 07/02/2018 S, Adam
7 Name3 GOP 0 OR2 Tab1 coe 1 07/02/2018 S, Adam
8 Name2 LNT 3 NE Tab1 st 4 07/01/2018 P, Silver
9 Name2 LNT 3 NE1 Tab1 co 2 07/01/2018 P, Silver
10 Name2 LNT 2 NE2 Tab1 st 3 07/01/2018 P, Silver
11 Name2 LNT 0 NE Tab9 co 5 07/01/2018 R, Henry
12 Name3 TTE 0 TT Tab1 ee 2 07/02/2018 R. Henry
13 Name3 TTE 0 T1 Tab1 ee 2 07/02/2018 R. Henry
I want to write a query that would give me the highest version of set together with distinct version 0.
For this I wrote the query as but this does not get my desired output:
var data = response.GroupBy(x => new { x.Name, x.Stream })
.SelectMany(g => g.OrderByDescending(row => row.Version).Take(1)) //This gives highest version
.Union(response.Where(x => int.Parse(x.Version) == 0)) // This gives version 0
.OrderByDescending(o => o.CreatedOn).ToList();
Desired Output On UI
Id Name Stream Version CreatedOn CreatedBy
4 Name1 GOP 2 07/02/2018 P, Silver //This is shown as 2 is the highest version for Name1 & GOP combination
5 Name2 GOP 1 07/02/2018 P, Silver //This is shown as Name & Stream combination is different
6 Name1 GOP 0 07/02/2018 S, Adam //Version 0 is always shown - Combination of Name & Stream may or may not have more than one 0 version
8 Name2 LNT 3 07/01/2018 P, Silver //This is shown as 3 is the highest version for Name2 & LNT combination
11 Name2 LNT 0 07/01/2018 R, Henry //Version 0 is always shown
12 Name3 TTE 0 07/02/2018 R, Henry //Version 0 is always shown
On the UI I am trying to just show the trimmed down version of a set. When the user clicks on that set I would then show details for all the individual sets within the set.
Right now I only struck with how to update my query so I can get my desired result.
----Updated---
Right now what I got working is individual lists:
var data1 = response.GroupBy(x => new { x.Name, x.Stream})
.SelectMany(g => g.OrderByDescending(row => row.Version).Take(1))
.Where(x => int.Parse(x.Version) != 0)
.OrderByDescending(o => o.CreatedOn).ToList();
The above gives me all latest versions for a given name and stream.
var data2 = response.GroupBy(x => new { x.Name, x.Stream})
.Select(g => g.First())
.Where(x => int.Parse(x.Version) == 0)
.OrderByDescending(o => o.CreatedOn).ToList();
The above gives me all 0 versions for a given name and stream.
I think these individual lists works fine at the moment, but how to merge them.
Is there a way to join/merge these lists together so as to return just a single set. Or if there is a way to merge these 2 linq queries together.
---Updated-----
var set1 = response.GroupBy(x => new { x.Name, x.Stream})
.SelectMany(g => g.OrderByDescending(row => row.Version).Take(1))
.Where(x => int.Parse(x.Version) != 0).ToList();
var set2 = response.GroupBy(x => new { x.Name, x.Stream, x.Version})
.Select(g => g.First())
.Where(x => int.Parse(x.Version) == 0).ToList();
var setmerged = set1.Union(set2).OrderByDescending(o => o.CreatedOn).ToList();
Got it working by above not sure if this is an clean solution.
Wrong use of DISTINCT
This doesn't make sense. DISTINCT is used to filter duplicate rows, which they aren't as only the version number is the same. Where should the DBS know from, which CreatedOn value it should use?
Better solution
What you want is to use GROUP BY in order to group everything with the same version value. Be aware that you'll need to use an aggregate function like MAX()on the other columns in order to use it correctly.
So from the looks of your updated question, you want the top one of each distinct version, name and stream.
According to the dataset you've provided, and the result sets you want, there is no need to do anything special for the 0 version because the conditions for grabbing the distinct version should include the 0 version as well.
You haven't really specified what the order of the version should be so for now I'll assume that the one that was most recently updated is the one you want
response.GroupBy(x => new { x.Name, x.Stream, x.Version })
.SelectMany(g => g.OrderByDescending(row => row.CreatedOn).Take(1))
.ToList();

How to Update Column based on another table column value

I have two data tables
table
id isfav
---------
1 1
2 1
3 1
4 1
5 1
favtable id
-----------
2 true
3 false
So I want to update the table1 column isFav to 0 if the ids exist in FavTable with false.
Can anybody help me with this?
You can use Any() to search in other entities.
var db = new YourDbContext();
var favtable = db.favtable.ToList();
//Find them:
var result = db.Table1.Where(t => favtable.Any(f => f.id == t.id && !f.isfav));
//result should be 3.
.NET Fiddle: https://dotnetfiddle.net/BmaqN5

How to do select multiple records based on max version using Entity Framework

I have records such like this
id name number version
---------------------------
1 NewYork 1 1
2 LosAngeles 1 2
3 Seatle 1 3
4 Toronto 2 1
5 Ottawa 2 2
I want to select only the records with highest version within the same number
So I wrote query like this
SELECT *
FROM city c
WHERE c.[version] = (SELECT Max([version])
FROM [city] c2
WHERE c2.number = c.number)
and it would return
id name number version
---------------------------
3 Seatle 1 3
5 Ottawa 2 2
How do I write that in linq with Entity Framework?
db.cities.where(c => c.version == (????))
I don't know how Entity Framework would work for this.
Use GroupBy to group by the number and then OrderBy the record with the highest version:
var result = db.cities.GroupBy(item => item.number)
.Select(grouping => grouping.OrderByDescending(item => item.version)
.First());
var maxVersionCities = db.cities
.GroupBy(c => c.number)
.Select(grp => grp
.OrderByDescending(c => c.version)
.First())
.SelectMany(grp => grp);

EF Query Help - Grouping and Sub queries

I have data table (DOCs, which is the DBSet in my context) with below data
ID Code Rev
1 A1 1
2 A1 2
3 A1 3
4 A3 1
5 A2 1
6 A2 2
I need to select the records which has a records for each Code which has the highest Rev. My expected result is
ID Code Rev
3 A1 3
6 A2 2
4 A3 1
The ID column is the PK of the table and Code+Rev is unique.
Note: There are other fields in the table which i need to get for the result. Ideal would be to get a iqueryable (Doc is the model class), i was think of selecting the ID within an inner query and then use that to get the iqueryable of docs.
Thanks in Advance
Try this:
var res = from r in DOCs
where (from c in DOCs
group c by c.Code into g
select new {
localCode = g.Key,
localRev = g.Max(t => t.Rev)
}).Any(x => x.localCode == r.Code && x.localRev == r.Rev)
select r;
res is IQueryable.

Categories