I have a table "ActivityMeasurements", from which i would like to get all different "MeasurementAttemptId" values for all "Athlete" values passed in. The problem is that different Athletes can have same MeasurementAttemptId, and with following piece of code i'm getting many duplicates even if "distinct" query is set to true.
Here is my code:
List<String> measAttempts = new ArrayList<String>();
String[] wheres = new String[globalRunnersList.size()];
String questionMarks = "";
for(int i = 0; i < globalRunnersList.size(); i++)
{
wheres[i] = globalRunnersList.get(i).getAthleteId();
questionMarks += ",?";
}
questionMarks = questionMarks.substring(1);
Cursor mCursor = db.query(true, "ActivityMeasurements", new String[] {"ActivityMeasurement _id", "MeasurementAttemptId", "Athlete"},"Athlete IN ("+questionMarks+")", wheres, null, null, null, null);
if(mCursor.moveToFirst())
{
do
{
measAttempts.add(mCursor.getString(mCursor.getColumnIndex("MeasurementAttemptId")));
}
while(mCursor.moveToNext());
}
return measAttempts;
I know i could just add some code to do this after, but i think there should be another way to do this.
Any help appreciated,
Regards
Use
public Cursor query (boolean distinct, String table, String[] columns, selection, String[], selectionArgs, String groupBy, String having, String orderBy, String limit)
instead of
public Cursor query(String table, String[] columns, String selection, String[] selectionArgs, String groupBy, String having, String orderBy)
and set disctinct parameter to true.
Stupid me, i found a solution already.
The problem was that my query was for multiple columns:
{"ActivityMeasurement _id", "MeasurementAttemptId", "Athlete"}
this way every line was different from other, so i got many results.
Then i changed it to just this:
{"MeasurementAttemptId"}
and this returns wanted results.
Related
the difference between query() and rawQuery() in SQLite when making more complex SQL queries.
for example
i want to use the SQL keyword DISTINCT, so I don't get any duplicates returned from the database.
i understand how to use rawQuery() method, that way you can put an actual SQL query statement in the method. in this way i can make a standard SQL statement with rawQuery. it would be easy to add the DISTINCT keyword to any SQL statement when using rawQuery()
however, when using the query() method as shown here in this code, I can't just use regular SQL statements. in this case, how would i make a query with the DISTINCT keyword as part of the query? or something with the same functionality?
// get info from country table
public String[] getCountries(int numberOfRows) {
String[] columns = new String[]{COUNTRY_NAME};
String[] countries = new String[numberOfRows];
int counter = 0;
Cursor cursor = sqLiteDatabase.query(COUNTRY_TABLE, columns,
null, null, null, null, null);
if (cursor != null){
while(cursor.moveToNext()){
countries[counter++] = cursor.getString(cursor.getColumnIndex(COUNTRY_NAME));
}
}
return countries;
}
Instead of the...
public Cursor query(String table, String[] columns, String selection,
String[] selectionArgs, String groupBy, String having,
String orderBy)
...method you're using, just use the...
public Cursor query (boolean distinct, String table, String[] columns,
String selection, String[] selectionArgs, String groupBy,
String having, String orderBy, String limit)
...overload and set distinct to true.
The Android docs seem a bit hard to direct link, but the doc page describing both is here.
you can use this,
Cursor cursor = db.query(true, YOUR_TABLE_NAME, new String[] { COLUMN1 ,COLUMN2, COLUMN_NAME_3 }, null, null, COLUMN2, null, null, null);
Here first parameter is used to set the DISTINCT value i.e if set to true it will return distinct column value.
and sixth parameter denotes column name which you want to GROUP BY.
You should use another QUERY function with first DISTINCT boolean parameter set to TRUE
public Cursor query (boolean distinct, String table,...)
this is the function i used in my app for getting distict name from a group table hope you get an idea ,have a look at it.only distinct values will be fetched if the column contains same names
public ArrayList<String> getGroupNames() {
ArrayList<String> groups = new ArrayList<>();
SQLiteDatabase db = this.getReadableDatabase();
String[] projection = {COLUMN_GROUP_NAME};
//select distinct values for group name from group table
Cursor cursor = db.query(true,GROUPS_TABLE_NAME, projection, null, null, COLUMN_GROUP_NAME, null, null,null);
if (cursor.moveToFirst()) {
do {
String group=cursor.getString(cursor.getColumnIndexOrThrow(COLUMN_GROUP_NAME));
groups.add(group);
Log.d("group",group+"gp");
}while (cursor.moveToNext());
}
return groups;
}
I want to return a cursor only with distinct values of a column.
The column 'Groups' has more items but with only 2 values: 1,2,1,1,1,2,2,2,1
String[] FROM = {Groups,_ID};
public Cursor getGroups(){
//......
return db.query(TABLE_NAME,FROM,null,null,null,null,null);
}
will return a cursor containing {1,2,1,1,1,2,2,2,1} but I would like to contain just {1,2}.
You can have an sql query like this,
public Cursor usingDistinct(String column_name) {
return db.rawQuery("select DISTINCT "+column_name+" from "+TBL_NAME, null);
}
you can use distinct argument while making query like this:
public Cursor query (boolean distinct, String table, String[] columns, String selection, String[] selectionArgs, String groupBy, String having, String orderBy, String limit)
Follow this doc for more clearity.
You can use below example query, as you have to give column name for distinct
Cursor cursor = db.query(true, YOUR_TABLE_NAME, new String[] { COLUMN_NAME_1 ,COLUMN_NAME_2, COLUMN_NAME_3 }, null, null, COLUMN_NAME_2, null, null, null);
COLUMN_NAME_2 - name of the column for distinct.
remember to add GROUP BY column names
Use boolean true iin the distinct argument, For example :
public Cursor query (**true**, String table, String[] columns, String selection, String[] selectionArgs, String groupBy, String having, String orderBy, String limit);
I have a database which has a column of dates in milliseconds. I'm trying to perform a query which allows me to retrieve only the dates that are greater than the current system time and in ascending order.
I've tried this query, but it causes my app to force close. I'm not sure whether the problem is the where clause part or the orderby clause part or both.
Here is what I done, your help would be most appreciative.
long lowestDate = 0;
long currentTime = System.currentTimeMillis();
String CT = Long.toString(currentTime);
String[]c = {CT};
mDb = mDbHelper.getReadableDatabase();
String[] dates = {KEY_DT};
Cursor getDate = mDb.query(DATABASE_TABLE, dates, dates + "> ?", c, null, null, dates + "ASC");
getDate.moveToFirst();
while(getDate.isAfterLast() == false)
{
lowestDate = getDate.getLong(0);
getDate.moveToNext();
}
It seems you are using query(String table, String[] columns, String selection, String[] selectionArgs, String groupBy, String having, String orderBy)
selection argument description:
A filter declaring which rows to return, formatted as an SQL WHERE clause (excluding the WHERE itself). Passing null will return all rows for the given table.
You should correct that. I think that's an issue, because you are calling toString() method on dates variable, which is an Array.
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);
What should I do to get my content provider to return the _count column with the count of records? The documentation says it is automatic, but maybe it's only taking about some built-in content provider. Running a query to the database seems not to return it.
If you are using contentProvider then you have to do it like count(*) AS count.
If you use cursor.getCount(), that would not be as efficient as the above approach. With cursor.getCount() you are fetching all the records just to get counts. The entire code should look like following -
Cursor countCursor = getContentResolver().query(CONTENT_URI,
new String[] {"count(*) AS count"},
null,
null,
null);
countCursor.moveToFirst();
int count = countCursor.getInt(0);
The reason why this works is because android needs a column name to be defined.
If you are using ContentProvider.query() a Cursor is returned. Call Cursor.getCount() to get a count of records in the returned cursor.
I had a similiar problem and found this worked for me. In the example below I wanted to get the count of images from the MediaStore provider.
final String[] imageCountProjection = new String[] {
"count(" + MediaStore.Images.ImageColumns._ID + ")",
};
Cursor countCursor = getContentResolver().query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
imageCountProjection,
null,
null,
null);
countCursor.moveToFirst();
int existingImageCount = countCursor.getInt(0);
With cursor.getCount() you can not assure that it returns the real number of items returned. There are much better ways:
1- If you are using Content Providers, you can do a query and use the Column (_COUNT) included in BaseColumns for your projection
#Override
public Cursor query(SQLiteDatabase db, Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
...
projection = new String[] {
ContentContract.NotificationCursor.NotificationColumns._COUNT,
};
...
Cursor cursor = queryBuilder.query(db, projection, selection, selectionArgs, groupBy, having, sortOrder);
return cursor;
}
2- To do a rawQuery using SELECT COUNT(*) as #saurabh says in his response.