I am Trying to get all the invoices in a single API hit.
Because, for every user having 100's of invoices.
It will exceed the API limit (Minute Limit: 60 calls in a rolling 60 second window).
I am trying to store all the invoice id into a single array and from that i will get the details of the user and then i loop the records locally and display it. It's the right way?
invoice_ids = user.estimates.select("invoice_id") || [] xero = Xeroizer::PrivateApplication.new(XERO_CONFIG["key"], XERO_CONFIG["secret"], XERO_CONFIG["path"], :rate_limit_sleep => 5)
invoices = ['795f789b-5958-xxxx-yyyy-48436dbe7757','987g389b-5958-xxxx-yyyy-68636dbe5589']
inv_id = invoice_ids.pluck(:invoice_id)
invoices = xero.Invoice.all(:where => 'InvoiceID==inv_id')
Also, I am getting the following error:
Xeroizer::ApiException (QueryParseException: No property or field 'inv_id' exists in type 'Invoice')
Looks like the problem is that you're not interpolating the inv_ids correctly. You probably need to do something like this:
invoices = xero.Invoice.all(:where => "InvoiceID==\"#{inv_id}\"")
You may have to perform some additional formatting on the inv_id variable to make it a valid Xero string. https://github.com/waynerobinson/xeroizer#retrieving-data
I'm attempting to make a linq where contains query quicker.
The data set contains 256,999 clients. The Ids is just a simple list of GUID'S and this would could only contain 3 records.
The below query can take up to a min to return the 3 records. This is because the logic will go through the 256,999 record to see if any of the 256,999 records are within the List of 3 records.
returnItems = context.ExecuteQuery<DataClass.SelectClientsGridView>(sql).Where(x => ids.Contains(x.ClientId)).ToList();
I would like to and get the query to check if the three records are within the pot of 256,999. So in a way this should be much quicker.
I don't want to do a loop as the 3 records could be far more (thousands). The more loops the more hits to the db.
I don't want to grap all the db records (256,999) and then do the query as it would take nearly the same amount of time.
If I grap just the Ids for all the 256,999 from the DB it would take a second. This is where the Ids come from. (A filtered, small and simple list)
Any Ideas?
Thanks
You've said "I don't want to grab all the db records (256,999) and then do the query as it would take nearly the same amount of time," but also "If I grab just the Ids for all the 256,999 from the DB it would take a second." So does this really take "just as long"?
returnItems = context.ExecuteQuery<DataClass.SelectClientsGridView>(sql).Select(x => x.ClientId).ToList().Where(x => ids.Contains(x)).ToList();
Unfortunately, even if this is fast, it's not an answer, as you'll still need effectively the original query to actually extract the full records for the Ids matched :-(
So, adding an index is likely your best option.
The reason the Id query is quicker is due to one field being returned and its only a single table query.
The main query contains sub queries (below). So I get the Ids from a quick and easy query, then use the Ids to get the more details information.
SELECT Clients.Id as ClientId, Clients.ClientRef as ClientRef, Clients.Title + ' ' + Clients.Forename + ' ' + Clients.Surname as FullName,
[Address1] ,[Address2],[Address3],[Town],[County],[Postcode],
Clients.Consent AS Consent,
CONVERT(nvarchar(10), Clients.Dob, 103) as FormatedDOB,
CASE WHEN Clients.IsMale = 1 THEN 'Male' WHEN Clients.IsMale = 0 THEN 'Female' END As Gender,
Convert(nvarchar(10), Max(Assessments.TestDate),103) as LastVisit, ";
CASE WHEN Max(Convert(integer,Assessments.Submitted)) = 1 Then 'true' ELSE 'false' END AS Submitted,
CASE WHEN Max(Convert(integer,Assessments.GPSubmit)) = 1 Then 'true' ELSE 'false' END AS GPSubmit,
CASE WHEN Max(Convert(integer,Assessments.QualForPay)) = 1 Then 'true' ELSE 'false' END AS QualForPay,
Clients.UserIds AS LinkedUsers
FROM Clients
Left JOIN Assessments ON Clients.Id = Assessments.ClientId
Left JOIN Layouts ON Layouts.Id = Assessments.LayoutId
GROUP BY Clients.Id, Clients.ClientRef, Clients.Title, Clients.Forename, Clients.Surname, [Address1] ,[Address2],[Address3],[Town],[County],[Postcode],Clients.Consent, Clients.Dob, Clients.IsMale,Clients.UserIds";//,Layouts.LayoutName, Layouts.SubmissionProcess
ORDER BY ClientRef
I was hoping there was an easier way to do the Contain element. As the pool of Ids would be smaller than the main pool.
A way I've speeded it up for now is. I've done a Stinrg.Join to the list of Ids and added them as a WHERE within the main SQL. This has reduced the time down to a seconds or so now.
I am not quite sure how to title this question and I am having a hard time getting it to work so here goes.
I have a hash of users which is various sizes. This can be anywhere from 2 to 40. I also have a hash of tickets which I want to search through and find any entries that do not contain the user_id of my users hash. I am not quite sure how to accomplish this. My last attempt I used this:
#not_found = []
users.each do |u|
#not_found += #tickets.select{|t| t["user_id"] != u.user_id}
end
I know this is not the right result as it does a comparison for only the one user_id. What I need to do is run through all of the tickets and pull out any results that contain a user_id that is not in the users hash.
I hope I am explaining this properly and appreciate any help!
Try this
known_user_ids = users.map(&:user_id)
tickets_with_unknown_users = #tickets.reject{ |t| known_user_ids.include?(t["user_id"]) }
I'm looking for a way to update all record with certain condition their cur_val + 100:
I have a table Suggestions with id and score fields, and I want all the entries with specific ids to receive a score bump, e.g:
Suggestion.where(id: ids_list).update_all(score: score+100)
How do I do that?
Try plain SQL, read about update_all:
Suggestion.where(id: ids_list).update_all('score = score + 100')
But remember update_all not trigger Active Record callbacks or validations.
Some tips:
You can do it in Ruby but this very bad:
Suggestion.where(id: ids_list).find_each do |x|
x.update(score: x.score + 100)
end
Things like this should happen in database.
I am using LINQ to write a query - one query shows all active customers , and another shows all active as well as inactive customers.
if(showall)
{
var prod = Dataclass.Customers.Where(multiple factors ) (all inactive + active)
}
else
{
var prod = Dataclass.Customers.Where(multiple factors & active=true) (only active)
}
Can I do this using only one query? The issue is that, multiple factors are repeated in both the queries
thanks
var customers = Dataclass.Customers.Where(multiple factors);
var activeCust = customers.Where(x => x.active);
I really don't understand the question either. I wouldn't want to make this a one-liner because it would make the code unreadable
I'm assuming you are trying to minimze the number of roundtrips?
If "multiple factors" is the same, you can just filter for active users after your first query:
var onlyActive = prod.Where(p => p.active == true);
Wouldn't you just use your first query to return all customers?? If not you'd be returning the active users twice.
Options I'd consider
Bring all customers once, order by 'status' column so you can easily split them into two sets
Focus on minimizing DB roundtrips. Whatever you do in the front end costs an order of magnitude less than going to the DB.
Revise user requirements. For ex. consider paging on results - it's unlikely that end user will need all customers at once.