linq sql where closest to number - c#

i have a table
Id Number
1 9
2 10
3 12
4 19
5 20
select Id where Number is closest to 18
it should return row 4 which is 19
how do i write this in linq and tsql? thanks

(from q in table
orderby Math.Abs(18 - q.Number)
select q).FirstOrDefault()
and
SELECT TOP 1
*
FROM
table
ORDER BY
ABS(10 - Number)
and for a datetime
var nearTo = new DateTime(1999, 12, 31);
(from q in table
orderby Math.Abs((nearTo - q.Date).TotalSeconds)
select q).FirstOrDefault()

Related

Converting a SQLServer to Linq Query

I would like to know what is the correct way to convert this query to LINQ.
SELECT DISTINCT ( CONVERT(date,FechaCreacion)) FROM Tabla
where ID = 4
order by CONVERT(date,FechaCreacion) desc
OFFSET (0 * 20) ROWS
FETCH NEXT 20 ROWS ONLY;
With this query it brings me this data:
1. 2021-03-16
2. 2021-03-15
3. 2021-03-14
4. 2021-03-13
5. 2021-03-11
6. 2021-03-09
7. 2021-03-02
8. 2021-02-28
9. 2021-02-25
10. 2021-02-24
11. 2021-02-23
12. 2021-02-22
13. 2021-02-21
14. 2021-02-19
15. 2021-02-10
16. 2020-11-30
17. 2020-10-05
18. 2020-02-18
LINQ:
var query = (from sp in esquema.Tabla
where sp.ID== 4
orderby DbFunctions.TruncateTime(sp.FechaCreacion) descending
select new
{
fechacreacion = DbFunctions.TruncateTime(sp.FechaCreacion)
}
).Skip(0* 20).Take(20).ToList().Distinct();
With LINQ it brings me less data than the query made directly in SQL Server
1. 2021-03-16
2. 2021-03-15
3. 2021-03-14
4. 2021-03-13
5. 2021-03-11
6. 2021-03-09
7. 2021-03-02
8. 2021-02-28
9. 2021-02-25
10. 2021-02-24
11. 2021-02-23
You have applied Distinct to already paginated result. That's why result is different.
var query =
from sp in esquema.Tabla
where sp.ID == 4
orderby DbFunctions.TruncateTime(sp.FechaCreacion) descending
select new
{
fechacreacion = DbFunctions.TruncateTime(sp.FechaCreacion)
};
var query = query
.Distinct()
.Skip(0 * 20)
.Take(20)
.ToList();

Column value be max value of another column where another value is the same

I need to update a column in the table... Let's call it MaxUsers, with the amount of different rows for the same User. So we have 4 columns:
Column 0: Unique ID
Column 1: User (Unique User ID, is the same for all subuser)
Column 2: SubUser Nr (this is 0 if it is the main user)
Column 3: MaxUsers (Maximum Subuser on this User)
I need column 3 (MaxUsers) to be the maximum number of Column 2 (SubUser Nr) where Row 1 is the same (User) is the same
I can do this in Linq on C# or even in python, but I am a bit of a newbie on SQL and doing over there would use many more queries than I think is needed, and I am pretty sure my method is not the most efficient.
If I was to do this in C# I would do it like this assuming the SQL database is queryable in LINQ:
// Grab all main users to an array
var MainUsers = SQLDatabase.Where(x => x.SubUser == 0).toArray();
// Go through them one by one
for(int i = 0;i < MainUsers.length();i++)
{
// Find all users in this user ID
var Group = SQLDatabase.Where(x => x.User = MainUsers[i].User).toArray();
// Go through each subuser
for(int o = 0; o < Group.Length();o++){
// If the subuser nr is bigger than the maxusers change it to that
if(Group[o].SubUserNr > Group[0]MaxUsers){
Group[0]MaxUsers = Group[o].SubUserNr;
}
}
// Sets the subusers to max value too
for(int o = 0; o < Group.Length();o++){
Group[o].MaxUsers = Group[0]MaxUsers
}
}
SQLDatabase.SaveChanges();
The final result would look like this
Row :UID / User / SubUser Nr/ MaxUsers
Row 0:0 / 10 / 0 / 3
Row 1:1 / 10 / 1 / 3
Row 2:2 / 10 / 2 / 3
Row 3:3 / 10 / 3 / 3
Row 4:4 / 15 / 0 / 4
Row 5:5 / 15 / 1 / 4
Row 6:6 / 15 / 2 / 4
Row 7:7 / 15 / 3 / 4
Row 8:8 / 15 / 4 / 4
Row 9:9 / 17 / 0 / 1
Row 10:10 / 17 / 1 / 1
I think this should achieve what you want:
UPDATE Users u
JOIN (SELECT uid, MAX(SubUser) AS max
FROM Users
GROUP BY uid) AS t
ON u.uid = t.uid
SET u.MaxUsers = t.max
It should take the max "subuser" for each user id, and then update the main user table with those values
Join two subqueries:
select t1.UID
, t1.User
, t1.[SubUser Nr]
, t2.MaxUsers
from (
select t.UID
, t.User
, t.[SubUser Nr]
from tbl t
) t1
inner join (
select t.UID
, t.User
, max(t.[SubUser Nr]) as MaxUsers
from tbl t
group by t.UID
, t.User
) t2 on t2.UID = t1.UID
and t2.User = t1.User
Or you may be able to use a correlated subquery.
select t1.UID
, t1.User
, t1.[SubUser Nr]
, (select max(t2.[SubUser Nr]
from tbl t2
where t2.User = t1.User) as MaxUsers
from tbl t1
(Sorry, my experience is in SQL Server. The syntax may need to be adjusted for MySQL.)
I am not sure I understand your question correctly, but I believe ultimately you want to have an extra column that tells you the latest user record to use?
var MainUsers = SQLDatabase.Where(x => x.SubUser == 0);
foreach (var user in MainUsers)
{
user.MaxUsers = MainUsers.Where(x => x.UID == user.UID).Max(x => x.SubUser);
}
Or you do not necessarily need to have an extra column but select in SQL by this query:
select UID, User, Max(SubUser)
from t1
group by UID, User, SubUser

Get data from SQLServer in ASC order

I have a table with column name id and value. While data is being saved in sql server database, it sorts itself in random order, i.e id value 1,2,3,4,5,6,7,14,15,16,17,8,9,10 and likewise.
I need to retrieve data in 4 groups with each having 11 data in asc id order,
that is,
Group 1: 1-11
Group 2 : 12-22
Group 3 : 23-33
Group 4 : 33-44
I have tried query
Group 1:select top(11) * from tblCode order by id ASC
Group 2:SELECT top(22)* FROM tblCode except select top(11) * from tblCode order by id ASC
Group 3:SELECT top(33)* FROM tblCode except select top(22) * from tblQRCode order by id ASC
group 4:SELECT top(44)* FROM tblCode except select top(33) * from tblCode order by id ASC
What my problem is since data are sorted randomly while saving them into database, they are retrieved randomly.
Below is the screenshot of how my data are saved in database.
help me select data as above mentioned group.
Use OFFSET and FETCH rather than TOP.
E.g. Group two would be:
select *
from tblCode
order by id ASC
offset 11 rows
fetch next 11 rows only
Complete repro script:
declare #t table (ID int not null, Value varchar(93) not null);
;With Numbers as (
select ROW_NUMBER() OVER (ORDER BY so1.object_id) as n
from sys.objects so1,sys.objects so2,sys.objects so3
)
insert into #t (ID,Value)
select n,'PEC-' + CONVERT(varchar(93),n)
from Numbers
where n between 1 and 1000
select *
from #t
order by id ASC
offset 11 rows
fetch next 11 rows only
Result:
ID Value
----------- ---------
12 PEC-12
13 PEC-13
14 PEC-14
15 PEC-15
16 PEC-16
17 PEC-17
18 PEC-18
19 PEC-19
20 PEC-20
21 PEC-21
22 PEC-22
This also get your desired results. For other queries change 33 with other values, now it get values from 33 to 22.
WITH t AS
( SELECT ROW_NUMBER() OVER (ORDER BY id) AS row_num, *
FROM tblCode )
SELECT TOP 11 *
FROM t
WHERE row_num > 33
Try this,
select * from Table Name Order by ID
I hope I am not misunderstand:
--Group 1
SELECT *
FROM tblCode
WHERE id >= 1
AND id <= 11
ORDER BY id ASC
--Group 2
SELECT *
FROM tblCode
WHERE id >= 12
AND id <= 22
ORDER BY id ASC
--Group 3
SELECT *
FROM tblCode
WHERE id >= 23
AND id <= 33
ORDER BY id ASC
You can also save the increments in variable. Maybe something like this (i.e) you send param group no 3:
--Group 3
SELECT #Group = 3 --just for sample, param should sent From application
SELECT #lastIndex = 3*11
SELECT #indexStart = #lastIndex - 10
SELECT *
FROM tblCode
WHERE id >= #indexStart
AND id <= #lastIndex
ORDER BY id ASC

SQL Select when data changes [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'd like to retrieve an integer value in a SQL Select but only when the data changes, e.g.:
Table data:
50 50 50 52 50 30 30 35 30 30 60 65 60 60
Now I'd like to get this data:
50 52 50 30 35 30 60 65 60
Executing a distinct query, this would not work for me because it would retrieve:
50 52 30 35 60 65
Any ideas?
I'm working with Entity Framework and C#, so suggestions using them would also be appreciated!
Thanks.
List<int> list=...;
var result=Enumerable.Range(0, list.Count- 1)
.Where(x=> x== list.Count-1 || list[x]!=list[x+1])
.Select(x=>list[x]);
fetch your results to dbResults then do
var results = new List<int>();
foreach (var element in dbResults)
{
if(!results.Any() || results.Last() != element)
{
results.Add(element);
}
}
int results will be list without consecutive duplicates
you can check it on ideone
This method is similar in principle to #wudzik's but instead of checking your result list each time, it simply stores the last int in a variable and checks against that instead.
var result = new List<int>();
int? previous;
foreach (var number in data)
{
if(!previous.HasValue || number != previous.Value){
{
result.Add(number);
previous = number;
}
}
return result
WITH cte as (--cte is your test data
SELECT
1 id,
50 value UNION SELECT
2,
50 UNION SELECT
3,
50 UNION SELECT
4,
52 UNION SELECT
5,
50 UNION SELECT
6,
30 UNION SELECT
7,
30 UNION SELECT
8,
35 UNION SELECT
9,
30 UNION SELECT
10,
30 UNION SELECT
11,
60 UNION SELECT
12,
65 UNION SELECT
13,
60 UNION SELECT
14,
60
),
temp AS --temp numbers the rows
( SELECT
id,
value,
ROW_NUMBER() OVER (ORDER BY id) rowno
FROM cte
)
SELECT
t2.value
FROM temp t1
INNER JOIN temp t2
ON t1.rowno = t2.rowno - 1 --join to the next row using rownumber
AND t1.value <> t2.value --but only return different values

How to add a Restriction to an inner join?

I have the following NHibernate DetatchedCriteria,
return DetachedCriteria.For<MMFund>()
.CreateCriteria<MMFund>(x => x.DataUniverse)
.Add<DataUniverse>(x => x.SiteId == 100)
.SetProjection(LambdaProjection.Property<MMFund>(x => x.FundId));
which is producing the following SQL:
and
this_.ShareClassReturn_ShareClassId in
(
SELECT f.[Fund_ID] as y0_
FROM
dbo.Fund f inner join CAP.DataUniverse du
on f.[Fund_TypeID] = du.[DataUniverse_TypeId]
and f.[Fund_CountryID] = du.[DataUniverse_CountryID]
WHERE fu.[DataUniverse_SiteId] = 100
)
There are many funds in a DataUniverse.
I need to filter this so that I can select only the funds with a country ID of 'ET', so that my query looks as follows:
and
scr.ShareClassReturn_ShareClassId in
(
/* Get funds in universe */
SELECT f.[Fund_ID] as y0_
FROM dbo.Fund f inner join CAP.DataUniverse du
on f.[Fund_TypeID] = du.[DataUniverse_TypeId]
and f.[Fund_CountryID] = 'ET' // these are the guys I need
WHERE du.[DataUniverse_SiteId] = 100
)
However, I'm not sure what I need to do to the DetachedCriteria in order to make this happen. The problem I'm having is that no matter what I do, it's putting the clause in the wrong place, such as
WHERE du.[DataUniverse_SiteId] = 100 and f.Fund_CountryId = 'ET'
when I add the line .Add(Restrictions.Eq("CountryId", "ET")) as follows
return DetachedCriteria.For<MMFund>()
.Add(Restrictions.Eq("CountryId", "ET"))
.CreateCriteria<MMFund>(x => x.DataUniverse)
.Add<DataUniverse>(x => x.SiteId == 100)
.SetProjection(LambdaProjection.Property<MMFund>(x => x.FundId));
or it attempts to filter on the wrong table entirely when I specify that the Restriction should be part of the second .CreateCriteria, such as
return DetachedCriteria.For<MMFund>()
.CreateCriteria<MMFund>(x => x.DataUniverse)
.Add(Restrictions.Eq("CountryId", "ET"))
.Add<DataUniverse>(x => x.SiteId == 100)
.SetProjection(LambdaProjection.Property<MMFund>(x => x.FundId));
which produces this;
WHERE du.[DataUniverse_SiteId] = 100 and du.[DataUniverse_CountryID] = 'ET'
** note - as I'm using the Criteria API, this is actually the Restriction that I'm using:
.Add<MMFund>(f => f.CountryId == "ET")
I used the Restriction terminology because it's more explicit to what I'm trying to achieve. The Criteria API & the other way both produce the exact same results.
Why do you think Where is the wrong place for the filter? That's where filtering happens.
The generated SQL looks sound. You have two tables joined on their common fields. The Where clause is providing the appropriate filtering information. If your preferred SQL statement was in place, you'd have data joined on TypeID alone, not the CountryID.
For example, let's say your Fund table looks like this
TypeID CountryID
1 1
1 2
2 1
2 2
3 1
4 1
And your DataUniverse table is the following
TypeID CountryID
1 1
1 2
1 3
2 1
2 2
2 3
3 1
3 2
4 1
4 2
If you wrote SQL like you desire, you would produce a join based on TypeID and you would filter Fund.CountryID = 1, for example. What would your product look like?
F.TypeID F.CountryID D.TypeID D.CountryID
1 1 1 1
1 1 1 2
1 1 1 3
2 1 2 1
2 1 2 2
2 1 2 3
3 1 3 1
3 1 3 2
4 1 4 1
4 1 4 2
Is that your desired output? Yes, you've filtered Fund.CountryID, but your join was just on TypeID, so you've got all records from DataUniverse with that matching type for each Fund.
With the join on the two fields and the Where filtering the CountryID, the result will be the following
F.TypeID F.CountryID D.TypeID D.CountryID
1 1 1 1
2 1 2 1
3 1 3 1
4 1 4 1
The question is which set of data is the one you expect?

Categories

Resources