1
votes

Need help here.

i managed to get the drinkName and categories working. http://dl.dropbox.com/u/418769/2.png

but i need to Distinct the categories and get a count value of the SQL database.

something like this http://dl.dropbox.com/u/418769/2.png and then this http://dl.dropbox.com/u/418769/3.png

how would i need to do to get it done ?

i need to run SELECT drinkID,drinkName from drinks,

SELECT DISTINCT categories from drinks &

count each categoies's row.. can it be done ?

this is my database looks like..http://dl.dropbox.com/u/418769/4.png

i'm following this http://mybankofknowledge.wordpress.com/2010/12/01/accessing-sqlite-from-iphone-table-view/

ok it kind of work.....i on this error

* Terminating app due to uncaught exception 'NSRangeException', reason: '* -[NSMutableArray objectAtIndex:]: index 5 beyond bounds [0 .. 4]'

  • (void) getInitialDataToDisplay:(NSString *)dbPath { DrinkTabsAndNavAppDelegate *appDelegate = (DrinkTabsAndNavAppDelegate *)[[UIApplication sharedApplication] delegate];

    if (sqlite3_open([dbPath UTF8String], &database) == SQLITE_OK) {

    const char *sql = "SELECT drinkID, drinkName FROM drinks";
    //const char *sql = "SELECT drinkName, categories FROM drinks";
    sqlite3_stmt *selectstmt;
    if (sqlite3_prepare_v2(database, sql, -1, &selectstmt, NULL) == SQLITE_OK) {
    
    while(sqlite3_step(selectstmt) == SQLITE_ROW) 
        {
            NSInteger primaryKey = sqlite3_column_int(selectstmt, 0);
            Drink *drinkObj = [[Drink alloc] initWithPrimaryKey:primaryKey];
            drinkObj.drinkName = [NSString stringWithUTF8String:(char *)sqlite3_column_text(selectstmt,1)]; 
            //drinkObj.categories = [NSString stringWithUTF8String:(char *)sqlite3_column_text(selectstmt, 6)];
    
            drinkObj.isDirty = NO;
            [appDelegate.drinksArray addObject:drinkObj];
            [drinkObj release];
        }
    
    
    }
    

    } else sqlite3_close(database); //close db to release all memory }

  • (void) getCategory:(NSString *)dbPath { DrinkTabsAndNavAppDelegate *appDelegate = (DrinkTabsAndNavAppDelegate *)[[UIApplication sharedApplication] delegate];

    if (sqlite3_open([dbPath UTF8String], &database) == SQLITE_OK) {

    const char *sql = "SELECT DISTINCT category FROM drinks";
    //const char *sql = "SELECT drinkName, categories FROM drinks";
    sqlite3_stmt *selectstmt;
    if (sqlite3_prepare_v2(database, sql, -1, &selectstmt, NULL) == SQLITE_OK) {
    
        while(sqlite3_step(selectstmt) == SQLITE_ROW) 
        {
            NSInteger primaryKey = sqlite3_column_int(selectstmt, 0);
            Drink *catObj = [[Drink alloc] initWithPrimaryKey:primaryKey];
            catObj.category = [NSString stringWithUTF8String:(char *)sqlite3_column_text(selectstmt, 0)];   
            //drinkObj.categories = [NSString stringWithUTF8String:(char *)sqlite3_column_text(selectstmt, 6)];
            NSLog(@"run here");
            catObj.isDirty = NO;
            [appDelegate.categoryArray addObject:catObj];
            [catObj release];
        }
    
    
    }
    

    } else sqlite3_close(database); //close db to release all memory }

3
The question is really hard to understand. Do you need a list of the categories and a count of how many drinks are in each ? What is wrong with the code that you posted ?Harald Scheirich
Hi Harald, Yes. i wanna do something like this :dl.dropbox.com/u/418769/2.png.....but now i can only do this: dl.dropbox.com/u/418769/1.pngDesmond
Do you want a count of the different drinks in each category?Tim
Yes tim, i wanna count it...something like this after tap dl.dropbox.com/u/418769/3.pngDesmond

3 Answers

2
votes

If you want a count of the drinks in each category:

           select category, count(drinkid) as DrinksInThisCategory
           from drinks
           group by category

But a properly normalized database would have a separate CATEGORIES table and you'd have a categoryid in your DRINKS table.

1
votes

There are two ways i can come up with, one is querying your db: SELECT drinkID FROM drinks where categories='catX' once per category, then count rows of each. I think this could be accomplished by using some SQLite code to return all the counts with a single query.

The other way is using you appDelegate.drinksArray. First order your query by categories, then you could use a predicate almost same as the one above and using FOR drink IN drinksArray (pseudo code here...) to count how many drinks have each category.

Performance wise, i think the best way is using sql to query both, drinks and count of each category, may be in two different queries o best in one.

1
votes

I would probably go with an approach that used an NSMutableDictionary instead of and array as the main datastructure.

-(void) addDrink:(Drink) drink
{
  //_drinks has been initialised earlier and is of type NSMutableDictionary
  NSMutableArray categoryDrinks = [_drinks objectForKey:drink.categories];
  if (categoryDrinks == nil)
  {
    categoryDrinks = [[[NSMutableArray alloc] init] autorelease];
    [_drinks setObject:categoryDrinks forKey:drink.categories];
  }

  [categoryDrinks addObject:drink];
}

This mimics the structure that you show in your images, the number of items in each category can now be found by calling [[_drinks objectForKey:categoryName] count]. Look at the apple documentation for NSMutableDictionary and NSMutableArray

If you just want the numbers there is the SQL GROUP BY expression you can get to the category counts doing something like this

SELECT CategoryColName, COUNT(CategoryColName) FROM TableName GROUP BY CategoryColName

This will give you pairs with the name of your category and the count

One small advice, in your Drinks object you use the property categories. I always try to keep the plurality of the name in sync with the type of data. This means I only use the plural for something if it is a collection of sorts. Otherwise I use the singular, this can be extended to SQL columns, while the column contains the categories of all the drinks. It is still only one category per drink. You did name the other columns using the singular.