Grouping Core Data Objects - iphone

I have a core data entity that has a created_at attribute which is a NSDate, and an amount attribute which is a NSInteger.
I would like to make a request that returns the sum of amounts grouped by months. Something like:
[['February 2010', 450], ['January 2010', 300]]
I'm not sure how to approach this, if I would have to first fetch all results for a specific date range, and then calculate sum, or if there are other methods.
P.S. I'm doing this on the iphone 4.2 sdk.

Even thought an answer has already be accepted let me add this more sophisticated and faster method for completeness.
Assuming the months aren't modeled in your data model, you will need to fetch the objects in each month and then sum the amounts. Repeat for as many months as you need.
So, the first step is to create a variable predicate for the fetch. Something like this:
NSPredicate *exPred=[NSPredicate predicateWithFormat:#"%#<=created_at<=%#", monthStartDate,monthEndDate];
NSPredicate *exPred=[NSPredicate predicateWithFormat:#"(%#<=created_at) AND (created_at<=%#)", monthStartDate,monthEndDate];
... then execute the fetch and sum the return:
NSNumber *theSum=[#sum.[context executeFetchRequest:theFetch error:&error].amount];
... or less cowboy:
NSArray *fetchedObjects=[context executeFetchRequest:theFetch error:&error];
// if no error
NSNumber *theSum=[fetchedObjects valueForKeyPath:#"#sum.amount"];
Put that in a loop for each month.
Predicates and collection operates are much faster than loops. Use them instead of loops whenever possible.

I'd fetch the range of objects you're interested into an array, then enumerate through that array and add all the amounts up on the go.
I'm not sure if this could be solved by creating a sophisticated request too, but my gut feeling tells me it would be tricky to set up anyway (if possible at all)...

Related

Tableau: Create a table calculation that sums distinct string values (names) when condition is met

I am getting my data from denormalized table, where I keep names and actions (apart from other things). I want to create a calculated field that will return sum of workgroup names but only when there are more than five actions present in DB for given workgroup.
Here's how I have done it when I wanted to check if certain action has been registered for workgroup:
WINDOW_SUM(COUNTD(IF [action] = "ADD" THEN [workgroup_name] END))
When I try to do similar thing with count, I am getting "Cannot mix aggregate and non-aggregate arguments":
WINDOW_SUM(COUNTD(IF COUNT([Number of Records]) > 5 THEN [workgroup_name] END))
I know that there's problem with the IF clause, but don't know how to fix it.
How to change the IF to be valid? Maybe there's an easier way to do it, that I am missing?
EDIT:
(after Inox's response)
I know that my problem is mixing aggregate with non-aggregate fields. I can't use filter to do it, because I want to use it later as a part of more complicated view - filtering would destroy the whole idea.
No, the problem is to mix aggregated arguments (e.g., sum, count) with non aggregate ones (e.g., any field directly). And that's what you're doing mixing COUNT([Number of Records]) with [workgroup_name]
If your goal is to know how many workgroup_name (unique) has more than 5 records (seems like that by the idea of your code), I think it's easier to filter then count.
So first you drag workgroup_name to Filter, go to tab conditions, select By field, Number of Records, Count, >, 5
This way you'll filter only the workgroup_name that has more than 5 records.
Now you can go with a simple COUNTD(workgroup_name)
EDIT: After clarification
Okay, than you need to add a marker that is fixed in your database. So table calculations won't help you.
By definition table calculation depends on the fields that are on the worksheet (and how you decide to use those fields to partition or address), and it's only calculated AFTER being called in a sheet. That way, each time you call the function it will recalculate, and for some analysis you may want to do, the fields you need to make the table calculation correct won't be there.
Same thing applies to aggregations (counts, sums,...), the aggregation depends, well, on the level of aggregation you have.
In this case it's better that you manipulate your data prior to connecting it to Tableau. I don't see a direct way (a single calculated field that would solve your problem). What can be done is to generate a db from Tableau (with the aggregation of number of records for each workgroup_name) then export it to csv or mdb and then reconnect it to Tableau. But if you can manipulate your database outside Tableau, it's usually a better solution

Calculate hash for java.sql.ResultSet

I need to know if the results of SQL query has been changed between two queries.
The solution a came up with is to calculate and compare some hash value based on ResultSet content.
What is the preferred way?
There are no such special hashCode method, for ResultSet that is calculated based on all retrieved data. Definetly you can not use default hashCode method.
To be 100% sure that you will take into account all the changes in the data,
you have to retrieve all columns from all the rows from ResultSet one by one and calculate hash code for them with any possible way. (Put everything into single String and get it's hashCode).
But it's very time consumption operation. I would propose you to execute extra query that calculate hash sum by itself. For example it can return count of rows and sum of all columns/rows... or smth like that..

ios coredata searching large datasets

I'm working on an enterprise ios application for the iphone that uses coredata as its persistence store. We have a couple core data entities and one of them has 30~ fields. My data set exceeds 45,000 of these 30-field entities.
I need to construct a query where my search string can match one of 12 different fields on the object. My NSPredicate is basically a big rats nest of (property == $A) || (otherproperty == $A) ... etc where $A is my search string.
We're just starting to tune this for performance because it's pretty bad. Are there any obvious things we should do? Would it be better to use compound predicates and just have each sub-predicate be (property == $A) ?
Thoughts? Thanks in advance.
My (partial) solution
- I watched some wwdc videos on core data and basically did what Apple said. Which was to create a relationship from my real object to another object to represent a search-token. This new search-token entity had two fields - token and weight. When I insert my main object into coredata I give him a set of these search-tokens. One search-token per field I want to query over and the contents of the token property are some sort of normalized (all lowercase) data. Then my predicate is simply "ANY searchTokens.token beginswith %#". So now we're just searching one table over its indexed field and we're not having to do any expersions in the right side of the where clause. Coredata is really fast searching like this. The only other thing I did was to put an NSTimer in shouldReloadTableForSearchString to only fire off the search after 1 second of inactivity.
UISearchDisplayController - wait for N seconds OR for user to press "Search" before conducting search
Using compound predicates will give you the same result as a long string with ||, so no, that won't help.
What might help is to optimize the order of the predicates. They're evaluated left to right, and evaluation stops as soon as the result is known. If you have a long chain of logical ORs, and the first one is true, it doesn't matter what the rest of them look like. Those predicates won't even be evaluated.
So, if you can reasonably expect that some properties are more likely to match than others, move those to the front of the list. If one will be YES almost all of the time, make that the first one.
Also, if any of these predicates are numeric, move those toward the front of the line. Numeric comparisons are much faster than string comparison, so any numeric check that returns YES will let you skip any following string comparisons.

iOS : Storing a table of rows and columns

Am just mulling over what's the best way i.e. data structure to store a data that has several rows and columns. Shoudl I store it as :
1. an array of arrays?
2. NSDictionary?
or is there any grid-like data structure in iOS where I can easily fetch any row/column with ease from the data structure? For example, I must be able to fetch the value in 3rd column in row 5. Currently, say, I store each row as an array and the store these arrays in another array (so an array of arrays, say), then to fetch the value in column 3 in row 5, I need to fetch the 5th row in the array of arrays, and then in the resulting array, I need to fetch the 3rd object. Is there a better way to do this? Thoughts please?
then to fetch the value in column 3 in row 5, I need to fetch the 5th
row in the array of arrays, and then in the resulting array, I need to
fetch the 3rd object. Is there a better way to do this?
An array of arrays is fine for the implementation, and the collection subscripting that was recently added to Objective-C makes this easier -- you can use an expression like
NSString *s = myData[m][n];
to get the string at the nth column of the mth row.
That said, it may still be a good idea to create a separate class for your data structure, so that the rest of your code is protected from needing to know about how the data is stored. That would also simplify the process of changing the implementation from, say, an array of arrays to a SQLite table or something else.
Your data storage class doesn't need to be fancy or complicated. Here's a first pass:
#interface DataTable
- (id)objectAtRow:(NSInteger)row column:(NSInteger)column;
- (void)setObjectAtRow:(NSInteger)row column:(NSInteger)column;
#end
I'm sure you can see how to implement those in terms of an array of arrays. You'll have to do a little work to add rows and/or columns when the caller tries to set a value outside the current bounds. You might also want to add support for things like fast enumeration and writing to and reading from property lists, but that can come later.
There are other ways of doing it, but there's nothing wrong with the method you are using. You could use an NSDictionary with a key of type NSIndexPath, for example, or even a string key of the form "row,col", but I don't see any advantage in those except for sparse matrices.
You can either use an array of arrays, as you're doing, or an array of dictionaries. Either is fine, and I don't think there's any preference for one over the other. It all depends on which way is most convenient for you to set up the data structure in the first place. Accessing the data for the table view is equally easy using either method.

SQL Sum and If/Case statements in NSArray

I currently make many calls to an SQL database to get sums of data, however the data is already in an NSArray so I would rather do my calculations on this instead.
I currently use this query on the SQL Database:
SELECT MAX(pk), pk, CASE WHEN result IS NULL THEN BFNeeded ELSE CFNeeded END AS Carry,
CASE WHEN result IS NULL THEN 1 ELSE 0 END AS Settle FROM table1;
I have a custom object that has several NSStrings the same as the SQL table (pk, BFNeeded, CFNeeded etc..) and I have several of these objects in an NSArray.
How can I perform the above query on the array?
Is there a way to perform SQL queries like above, or do I need to take a totally different approach to do the CASE?
Thanks
Check out Key Value Coding operators, which may accommodate the type of operations on an array that you are seeking:
http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/KeyValueCoding/Articles/CollectionOperators.html#
You may seek to filter or predicate your array, for example, you can iterate an array with a block or obtain a subset of objects that meet certain criteria or pass a test, for example with:
NSArray *filteredArray = [myArray filteredArrayUsingPredicate:myPredicate];
Then use a KVC operator for a calculation on the result set.