I am writing an android application that is trying to pull data from a database based on two separate criteria.
The fields of workout and exercise are both strings in the database. I want to return a cursor with only those rows that satisfy BOTH criteria. Oh and I would also like it to be sorted in date order...
public Cursor graphQuery(String exercise, String workout) {
Cursor cursor = mDb.query(DATABASE_TABLE, new String [] {KEY_DATE, KEY_REPS,
KEY_REPS_FEEL, KEY_WEIGHT, KEY_WEIGHT_FEEL}, "KEY_WORKOUT=" + workout + "AND" +
"KEY_EXERCISE=" + exercise, null , null, null, KEY_DATE);
return cursor;
}
I am a new android coder and would appreciate the help!
Use selection and selectionArgs:
public Cursor graphQuery(String exercise, String workout) {
Cursor cursor = mDb.query(DATABASE_TABLE, new String [] {KEY_DATE, KEY_REPS,
KEY_REPS_FEEL, KEY_WEIGHT, KEY_WEIGHT_FEEL}, "KEY_WORKOUT = ? AND KEY_EXERCISE = ?",
new String[] { workout, exercise },
null,
null,
KEY_DATE);
return cursor;
}
Notice how the selection String has ?s inplace of actual values and the actual values are passed in as a String[] and in the selectionArgs paramter. SQLite will replace those ?s with the values from the String[] selectionArgs.
Short answer: There are spaces missing around "AND" --> " AND ".:
Long answer: Please use parameter markers - you will see missing spaces immediately then:
Cursor cursor = mDb.query(DATABASE_TABLE, new String [] { KEY_DATE, KEY_REPS,
KEY_REPS_FEEL, KEY_WEIGHT, KEY_WEIGHT_FEEL }, "KEY_WORKOUT=? and KEY_EXERCISE=?", new String[] { workout, exercise }, null, null, KEY_DATE);
Related
I have a query that gets data from an sqlite database based on the Day value using a where clause, The data i'm getting is for 'Monday' this data is then populated into a listview. In addition to this i want to order the data by the time in ascending order to form a list with all events on monday from the earliest to latest Start times.
Query by day:
public Cursor getMonday () {
String Monday = "Monday";
return db.query(
DATABASE_TABLE,
new String[] { KEY_ID, KEY_LESSON, KEY_DAY, KEY_START, KEY_END, KEY_LOCATION},
KEY_DAY + "=?",
new String[] {Monday},
null, null, null);
}
I've tried:
public Cursor getMonday () {
String Monday = "Monday";
return db.query(DATABASE_TABLE,
new String[] {KEY_ID, KEY_LESSON, KEY_DAY, KEY_START,KEY_END, KEY_LOCATION},
KEY_DAY + "=?",
new String[] {Monday},
null, null, null,
KEY_START + " ASC");
}
This would usually work but i imagine that the WHERE clause and order by are not in the right order and i dont know how to make them work in unison. Could someone please advise? Thanks.
This is the error im getting:
01-28 14:24:02.738: E/AndroidRuntime(1672): FATAL EXCEPTION: main
01-28 14:24:02.738: E/AndroidRuntime(1672): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.unischeduler/com.example.unischeduler.ScheduleActivity}: java.lang.IllegalArgumentException: invalid LIMIT clauses:Start ASC
Your argument order is incorrect, try this:
public Cursor getMonday () {
String Monday = "Monday";
return db.query(DATABASE_TABLE,
new String[] {KEY_ID, KEY_LESSON, KEY_DAY, KEY_START,
KEY_END, KEY_LOCATION}, KEY_DAY + "=?",
new String[] {Monday}, null, null, KEY_START + " ASC", null);
}
EDIT Proposal to order by hh:mm format:
Take a look to SQLite Date and Time Functions and maybe you could try (I haven't tested it) something like this:
return db.query(DATABASE_TABLE,
new String[] {KEY_ID, KEY_LESSON, KEY_DAY, KEY_START,
KEY_END, KEY_LOCATION}, KEY_DAY + "=?",
new String[] {Monday}, null, null, "strftime('%H:%M', " + KEY_START + ")", null);
Very simple task it would seem, trying to get a given range of records/rows in my SQLite db in Android app with the following :
String[] projection = {"_id"};
String selection = "_id between ? and ?";
String[] selectionArgs = {"1", "10"};
queryBuilder.query(db, projection, selection, selectionArgs, null, null, null);
With the above selectionArgs I'm getting just the two rows, row 1 and 10. If I change arg to anything else I'm getting the whole lot (entire set of records/rows) as if there was no condition. Been banging my head for a day why this works the way it does, perhaps there's some special thing to know about the use of "between" in SQLite ? Any comments/help much appreciated.
You can use this code.
private SQLiteDatabase productDatabase;
public Cursor get_result(){
Cursor c;
String sql = "SELECT * FROM " + tableName +"WHERE _id BETWEEN" + value1 +"AND" + value2;
c = productDatabase.rawQuery(sql, null);
}
Cursor cursor=get_result();
if(cursor.moveToNext()){
Log.d("count of product id="+cursor.getString(0));
}
Seems problem from your side I checked and it works fine,
Method
public Cursor GetBetween(String[] projection,String selection, String[] args){
return db.query(TBL_NAME, projection, selection, args, null, null, null);
}
Implementation
String[] projection = new String[]{"_id"};
String[] selectionArgs = new String[]{"1","3"};
String selection = "_id between ? and ?";
Cursor cursorGetBetween = helper.GetBetween(projection,selection, selectionArgs);
startManagingCursor(cursorGetBetween);
cursorGetBetween.moveToFirst();
while(!cursorGetBetween.isAfterLast()){
Log.d("value of cursorGetBetween", cursorGetBetween.getString(0));
cursorGetBetween.moveToNext();
}
Output
01-31 18:42:58.176: D/value of cursorGetBetween(647): 1
01-31 18:42:58.176: D/value of cursorGetBetween(647): 2
01-31 18:42:58.176: D/value of cursorGetBetween(647): 3
I am making a query on the Android Contacts ContentProvider. I need a Group By clause. In Gingerbread and Honeycomb, I do something like this to search phone numbers and emails at the same time:
(The actual WHERE clause is much more complicated as it includes types checks. This is a simplification, but it yields the same result)
String request = Phone.NUMBER + " LIKE ? OR " + Email.DATA + " LIKE ?";
String[] params = new String["%test%", "%test%"];
Cursor cursor = getContentResolver().query(
Data.CONTENT_URI,
new String[] { Data._ID, Data.RAW_CONTACT_ID },
request + ") GROUP BY (" + Data.RAW_CONTACT_ID,
params, "lower(" + Data.DISPLAY_NAME + ") ASC");
The injection of the ')' finishes the WHERE clause and allow the insertion of a GROUP BY clause.
However, in Ice Cream Sandwich, it appears that the ContentProvider detects this and adds the correct number of parenthesis to prevent my injection. Any other way of doing this in a single cursor query?
Edit
Currently, I have removed the GROUP BY, and added a MatrixCursor to limit the impact, but I'd rather have a real cursor:
MatrixCursor result = new MatrixCursor(new String[] { Data._ID, Data.RAW_CONTACT_ID });
Set<Long> seen = new HashSet<Long>();
while (cursor.moveToNext()) {
long raw = cursor.getLong(1);
if (!seen.contains(raw)) {
seen.add(raw);
result.addRow(new Object[] {cursor.getLong(0), raw});
}
}
I recently battled this issue querying the CallLog.Calls DB (where we were not able to modify the ContentProvider). What we ended up going with was building a query that looked like this:
SELECT _id, date, duration, type, normalized_number FROM calls WHERE _id IN (
SELECT _id FROM calls WHERE date < ? GROUP BY normalized_number ORDER BY date DESC LIMIT ?
);
The idea here is that we place any valid sqlite in our subquery, return a list of ids and then query again for all calls with those ids.
The final code looked something like this:
String whereClause = "_id IN (SELECT _id FROM calls WHERE data < ? GROUP BY normalized_number ORDER BY date DESC LIMIT ?)";
Cursor cursor = context.getContentResolver().query(
CallLog.Calls.CONTENT_URI,
new String[] { "_id", "date", "duration", "normalized_number" },
whereClause,
new String[]{ String.valueOf(amount), String.valueOf(dateFrom) },
null
);
...
In the case that you're querying for contacts, it would look something like this:
String whereClause = "_id IN (SELECT _id FROM contacts WHERE " + Phone.NUMBER + " LIKE ? OR " + Email.DATA + " LIKE ? GROUP BY " + Data.RAW_CONTACT_ID + " ORDER BY lower(" + Data.DISPLAY_NAME + ") ASC)";
String[] params = new String["%test%", "%test%"];
Cursor cursor = getContentResolver().query(
Data.CONTENT_URI,
new String[] { Data._ID, Data.RAW_CONTACT_ID },
whereClause,
params,
null
);
There will be some decrease in performance (since we're essentially querying twice for the same results), but it will surely be a lot faster than querying for all calls and doing the GROUP BY work in java world and also allows you to build up the query with additional clauses.
Hope this helps. We used this on Oreo and it fulfilled our needs.
You could create a custom Uri such that when your UriMatcher in your ContentProvider gets it, you can insert your group by clause and then execute the raw sql directly on the database.
first off all excuse my POOR English!
I'm new to Java/Android, started with 4.2.1 and fight with that too almost 2 days, then i start reading some more details about SQLiteQueryBuilder the query part is pretty much that what u are looking for ;)
it have:
public Cursor query (SQLiteDatabase db, String[] projectionIn, String selection, String[] selectionArgs, String groupBy, String having, String sortOrder)
the query "function" of the Content Provider only gives you:
query(Uri uri, String[] projection, String selection,String[] selectionArgs, String sortOrder)
here u can trick around, i will post you my code snip:
#Override
public Cursor query(Uri uri, String[] projection, String selection,
String[] selectionArgs, String sortOrder) {
SQLiteQueryBuilder queryBuilder = new SQLiteQueryBuilder();
final SQLiteDatabase db = mOpenHelper.getReadableDatabase();
/* a String is a Object, so it can be null!*/
String groupBy = null;
String having = null;
switch (sUriMatcher.match(uri)) {
...
...
...
case EPISODES_NEXT:
groupBy = "ShowID";
queryBuilder.setTables(EpisodenTable.TableName);
break;
default:
throw new IllegalArgumentException("Unknown URI " + uri);
}
Cursor c = queryBuilder.query(db, projection, selection, selectionArgs,
groupBy, having, sortOrder);
c.setNotificationUri(getContext().getContentResolver(), uri);
return c;
}
thats its!
here the code i use to execute:
Cursor showsc = getContext().getContentResolver().query(
WhatsOnTVProvider.CONTENT_EPISODES_NEXT_URI,
EpisodenTable.allColums_inclCount,
String.valueOf(Calendar.getInstance().getTimeInMillis() / 1000)
+ " < date", null, null);
I would like to limit the results to those whose KEY_HOMEID is equal to journalId.
I've been on this for a couple days any help would be appreciated.
public Cursor fetchAllNotes(String journalId)
{
return mDb.query(DATABASE_TABLE, new String[] {KEY_ROWID, KEY_HEIGHT,
KEY_BODY, KEY_HOMEID},"FROM DATABASE_TABLE WHERE KEY_HOMEID = journalId",null, null, null, null,null);
}
Have a look at http://developer.android.com/reference/android/database/sqlite/SQLiteDatabase.html#query
Your query should look a little like this:
mDb.query(DATABASE_TABLE, // Table name
columnNames, // String[] containing your column names
KEY_HOMEID+" = "+jounalId, // your where statement, you do not include the WHERE or the FROM DATABASE_TABLE parts of the query,
null,
null,
null,
null
);
If you feel more comfortable writing sql queries you can also use:
mDb.rawQuery("SQL STATEMENT", null);
It makes your code more clear if you'll use it where arguments (in query parameters)
Example:
String [] settingsProjection = {
DBContract.Settings._ID,
DBContract.Settings.COLUMN_NAME_USER_ID,
DBContract.Settings.COLUMN_NAME_AUTO_LOGIN
};
String whereClause = DBContract.Settings.COLUMN_NAME_USER_ID+"=?";
String [] whereArgs = {userId.toString()};
Cursor c = db.query(
DBContract.Settings.TABLE_NAME,
settingsProjection,
whereClause,
whereArgs,
null,
null,
null
);
I was looking for an answer to my problem here as well.
It turned out that I tried to have a String instead of an Integer. My solution was to do it like that: 'String' instead of Integer.
Here is the code that worked for me in the end:
return db.query(TABLE_NAME_REMINDER, PROJECTION, REMINDER_REMINDER_TYPE+" = '"+rem_type+"'", null, null, null, null);
I am trying to use this query upon my Android database, but it does not return any data. Am I missing something?
SQLiteDatabase db = mDbHelper.getReadableDatabase();
String select = "Select _id, title, title_raw from search Where(title_raw like " + "'%Smith%'" +
")";
Cursor cursor = db.query(TABLE_NAME, FROM,
select, null, null, null, null);
startManagingCursor(cursor);
return cursor;
This will return you the required cursor
Cursor cursor = db.query(TABLE_NAME, new String[] {"_id", "title", "title_raw"},
"title_raw like " + "'%Smith%'", null, null, null, null);
Alternatively, db.rawQuery(sql, selectionArgs) exists.
Cursor c = db.rawQuery(select, null);
This will also work if the pattern you want to match is a variable.
dbh = new DbHelper(this);
SQLiteDatabase db = dbh.getWritableDatabase();
Cursor c = db.query(
"TableName",
new String[]{"ColumnName"},
"ColumnName LIKE ?",
new String[]{_data+"%"},
null,
null,
null
);
while(c.moveToNext()){
// your calculation goes here
}
I came here for a reminder of how to set up the query but the existing examples were hard to follow. Here is an example with more explanation.
SQLiteDatabase db = helper.getReadableDatabase();
String table = "table2";
String[] columns = {"column1", "column3"};
String selection = "column3 =?";
String[] selectionArgs = {"apple"};
String groupBy = null;
String having = null;
String orderBy = "column3 DESC";
String limit = "10";
Cursor cursor = db.query(table, columns, selection, selectionArgs, groupBy, having, orderBy, limit);
Parameters
table: the name of the table you want to query
columns: the column names that you want returned. Don't return data that you don't need.
selection: the row data that you want returned from the columns (This is the WHERE clause.)
selectionArgs: This is substituted for the ? in the selection String above.
groupBy and having: This groups duplicate data in a column with data having certain conditions. Any unneeded parameters can be set to null.
orderBy: sort the data
limit: limit the number of results to return
Try this, this works for my code
name is a String:
cursor = rdb.query(true, TABLE_PROFILE, new String[] { ID,
REMOTEID, FIRSTNAME, LASTNAME, EMAIL, GENDER, AGE, DOB,
ROLEID, NATIONALID, URL, IMAGEURL },
LASTNAME + " like ?", new String[]{ name+"%" }, null, null, null, null);