Linq - Limit number of results by same value of a field - entity-framework

I have a problem with a creation of a Linq to Entities (Oracle 11g) request. Here is the
I have a table TREATMENT with three column (simplified version) : ID, STATE and APPLICATION. Here is a sample :
ID STATE APPLICATION
1 A MAJ
2 A FLUX
3 A FLUX
4 R REF
5 A REF
Now, my objectives are to retrieve the data with theses rules:
State must be A (added)
Number of rows per application below a max value
The max value is minored b the number of row with State = R (per application)
Exemple : If the max value is 1, I must retrieve row 1 and 2. (Can't retrieve row 5 since there is already a REF with state R (the row 4))
I manage to retrieve all the row when the number of R is equal or greater than the max value, but I don't see how to limit my number of result in order to respect the max value.
Here is the request :
using (Entities bdd = new Entities())
{
var treatments = from trt in bdd.TREATMENT
let app = from t in bdd.TREATMENT
where t.STATE == "R"
group t by t.APPLICATION into grouped
where grouped.Count() >= maxPerApplication
select grouped.Key
where trt.STATE == "A" && !app.Contains(trt.APPLICATION)
orderby trt.ID
select new TreatmentDto()
{
Id = trt.ID
};
result = treatments.ToList();
}
In SQL, I would use an inner request and a ROWNUM to limit the number of result, but I don't see how to do it. The only solution I see is to do the request in two parts, but I want to avoid this to maintain the consistency of the information.

I found a solution, not sure if it's the best, but it works :
using (Entities bdd = new Entities())
{
from trt in bdd.TREATMENT
where trt.STATE == "A" &&
(from trt2 in bdd.TREATMENT
where trt2.STATE == "A" && trt2.APPLICATION == trt.APPLICATION && trt2.ID <= trt.ID
select trt2).Count() <= maxPerApplication - (from appp in bdd.TREATMENT
where appp.STATE == "R"
&& appp.APPLICATION.Equals(trt.APPLICATION)
select appp).Count()
select new TreatmentDto()
{
Id = trt.ID
};
result = treatments.ToList();
}

Related

Couchbase Update query divide

I am trying to update the document using the UPDATE query statement on the couchbase.
EX)
UPDATE Users SET cityIndex = 1 where Users.city= "NewYork";
There was so much data that I wanted to divide 3,000 to 4,000 and proceed with the UPDATE. How should I proceed?
There is PRIMARY INDEX.
The Eventing Function method that vsr alluded too is quite simple (7 lines sans comments) and you run it as a one-off point tool deploying it from Everything. Note there is no need for any index for this to work.
// To run configure the settings for this Function, UpdateAllCityIndex, as follows:
//
// Version 7.0+
// "Listen to Location"
// bulk.data.yourcollection
// "Eventing Storage"
// rr100.eventing.metadata
// Binding(s)
// 1. "binding type", "alias name...", "bucket.scope.collection", "Access"
// ---------------------------------------------------------------------------
// "bucket alias", "src_col", "bulk.data.Users", "read and write"
//
// Version 6.X
// "Source Bucket"
// yourbucket
// "MetaData Bucket"
// metadata
// Binding(s)
// 1. "binding type", "alias name...", "bucket", "Access"
// ---------------------------------------------------------------------------
// "bucket alias", "src_col", "Users", "read and write"
//
// For more performance set the workers to the number of physical cores
function OnUpdate(doc, meta) {
// only process documents with the city field
if (!doc.city) return;
// only update New York if cityIndex isn't already 1 or does not exist
if ( doc.city === "NewYork" && (!doc.cityIndex || doc.cityIndex !== 1 )) {
doc.cityIndex = 1;
// write back the updated doc via the alias
src_col[meta.id] = doc;
}
}
Option 1)
You can use couchbase eventing
case 2 of https://docs.couchbase.com/server/current/eventing/eventing-example-data-enrichment.html
https://docs.couchbase.com/server/current/eventing/eventing-examples.html
Option 2)
CREATE INDEX ix1 ON Users (city, cityIndex);
UPDATE Users AS u
SET u.cityIndex = 1
WHERE u.city = "NewYork" AND u.cityIndex != 1
LIMIT 4000;
Using a primary index, you can issues multiple queries on a (presumably stable primary index) and iterate over it. Little bit more complicated, but generalized.
rq is the bucket, s is the scope, t1 is the collection.
create collection rq.s.t1;
create primary index on rq.s.t1;
First query:
UPDATE rq.s.t1 USE KEYS [(
SELECT META().id
FROM rq.s.t1
ORDER BY META().id
LIMIT 10)] SET x = 1 RETURNING MAX(META().id);
Second to N query until you're done (nothing gets returned):
Take the max value of meta().id from the previous query (see the WHERE clause)
UPDATE rq.s.t1 USE KEYS [(
SELECT RAW META().id
FROM rq.s.t1
WHERE META().id > "007dd444-fa39-498f-b070-6cd0d41abe3d"
ORDER BY META().id
LIMIT 10)] SET x = 1 RETURNING META().id;
You can optimize this loop by setting the initial meta().id to compare against "".

why my Linqued query is not getting executed

I have this linqued query
var moreThen1dayLeavefed = (from LApp in db.LeaveApplications
join Emp in db.Employees
on LApp.Employee equals Convert.ToInt32(Emp.EmployeeNumber)
join LBrk in db.LeaveBreakups
on LApp.Id equals LBrk.LeaveApplication
where Emp.Team == 8 && LBrk.StartDate.Year == 2015 && LBrk.StartDate.Month == 5
select new { StartDate = LBrk.StartDate.Day, EndDate = LBrk.EndDate.Day, diff = (DbFunctions.DiffDays(LBrk.StartDate, LBrk.EndDate) + 1) }).ToList();
it gives error
LINQ to Entities does not recognize the method 'Int32 ToInt32(System.String)' method, and this method cannot be translated into a store expression.
on line 3, i.e
on LApp.Employee equals Convert.ToInt32(Emp.EmployeeNumber)
as I am converting the string to int during inner join
Just saw your related question. Your EmployeeNumber field seems to be filled with fixed size (5) zero left padded string representation of a number. If that's true, you can use the trick from how to sort varchar column containing numeric values with linq lambdas to Entity to solve the issue.
Just replace
on LApp.Employee equals Convert.ToInt32(Emp.EmployeeNumber)
with
on DbFunctions.Right("0000" + LApp.Employee.ToString(), 5) equals Emp.EmployeeNumber

Order By on specific column

I am trying to get the distinct records
var records = (from entry in db.Table1
select new
{
RowID = entry.RowID,
FirstName = entry.First,
LastName = entry.Last,
Restricted = (entry.Prohibited == null || entry.Prohibited == "False") ? "Restricted" : "Not Restricted"
}).ToList();
Here RowID is an primary key. I want to get the distinct First and Last Name.
For example:
RowID First Last Prohibited ...
1 A B False
2 A B False
3 A B False
4 Z Y True
5 Z Y True
What I am trying to get here is:
RowID First Last Prohibited
1 A B False
4 Z Y True
How can I get it?
var records = (from entry in db.Table1
group entry by new {entry.First, entry.Last} into g
let entry = g.FirstOrDefault()
select new
{
RowID = entry.RowID,
FirstName = entry.First,
LastName = entry.Last,
Restricted = (entry.Prohibited == null || entry.Prohibited == "False") ? "Restricted" : "Not Restricted"
}).ToList();
By grouping the items by the combined first and last name, and then only taking the first item in each group, you effectively ensure that you're getting distinct items based on those values.
Simply you can do in this way:
var records =
(from entry in db.Table1
select new {
FirstName = entry.First,
LastName = entry.Last,
Restricted = (entry.Prohibited == null || entry.Prohibited == "False") ? "Restricted" : "Not Restricted"
}).Distinct();
If you want the rowID also, you can read select-distinct-using-linq.

Calculating Average Timespan between two dates in Entity Framework

I have a database table with two columns: StartDateTime and FinishDateTime. both are nullable datetime columns.
I'm wanting to calculate the Average time between both fields per row. ie the average duration of my recorded event.
I'm getting a "DbArithmeticExpression arguments must have a numeric common type."
Example EF code with a touch of simplification for the demo.
from p in new DbContext()
where p.user_id = 123
&& p.StartDateTime != null
&& p.FinishDateTime != null
select new {p.StartDateTime, p.FinishDateTime})
.Average(p=> (p.FinishDateTime.Value - p.StartDateTime.Value).Ticks)
I'd love an example of the above, as SQL makes this a breeze.
Its depends on your data provider, it may support DbFunctions and you could do something like this:
(from p in new DbContext()
where p.user_id = 123
&& p.StartDateTime != null
&& p.FinishDateTime != null
select new {p.StartDateTime, p.FinishDateTime})
.Average(x=> DbFunctions.DiffMilliseconds(p.FinishDateTime,p.StartDateTime))
if it doesn't, i think you have to go linq to objects after the select:
(from p in new DbContext()
where p.user_id = 123
&& p.StartDateTime != null
&& p.FinishDateTime != null
select new {p.StartDateTime, p.FinishDateTime})
.ToArray()
.Average(x=> (p.FinishDateTime -p.StartDateTime).Ticks)

How to join the tables in linq to sql?

Table1 :
userid name address
1 venkat srinagr
2 venkatesh sainagar
Table2:
id userid lat lon
1 1 14.000 15.000
2 2 14.3526 15.3698
by passing "venkat" as parameter then need to pull all matching records and his userid,name,lat,lon.
in above table1 "venkat" contains in both rows then need to pull 2 records.how to get userid,name,lat,lon for all matching rows..
for sigle record i am able to get.but there are multiple rows how to get please tell me....
var result = from p in cxt.Table2
where p.Table1.Name.Contains(name)
select new
{
p.Users.User_Id,p.Users.Name,p.Latitude,p.Longitude
};
Im sure someone will say this is not the most effective way but this is how i would do it.
string InputString = "venkat";
var tab =(from a in db.tablea
from b in db.tableb
where a.userid == b.userid && a.name == InputString
select new
{
UserID = a.userid,
Username = a.name,
Latitude = b.lat,
Longditude = b.lon
}).FirstOrDefault();
FirstOrDefault() is only if you want to force only one output or null,
if you want a collection of some sort, then just remove it.