cursor count(*) getCount working badly - android

I want to check if there's a record in my table Users corresponding to an id_user, in case there isn't I will add it. The problem is that my Cursor.getCount() returns 1 and it doesn't make sense because my table is completely empty.
Cursor c = db.rawQuery("SELECT count(*) FROM Users WHERE id_user = '"
+ jsonObj.getString("id_user") + "'", null);
Log.i("getUser cursor",c.getCount() + ""); // it prints 1
c.moveToFirst();
int ic = c.getInt(0);
Log.i("getUser count2", ic + ""); // it prints 0
Why c.getCount() is giving me 1 when there is not absolutely any record. However, c.getInt(0) seems to work fine.
Thanks

Because you are getting a row back in your query.
Select count(*)
will return one rows containing the count of records. The count of records is 0, thus it returns one row, containing the value 0.
Select *
then
c.getCount()
Would return the 0 you are expecting because you are pulling back all rows, (not a count of rows) and there are no rows. But this is a bad approach since it can pull back extra data and might be slow.
in this case
int ic = c.getInt(0); is the proper way to get the data you want.

Related

I'm trying to get the first Min value from a SQL database in android

Sorry, I'm new. I have a table and need to get the column ID of the first min value of the table. The table is organized so the values keep decreasing until they get to 0 and all subsequent values are equal to zero.
It is possible for none of the values to be zero in which case Id need the last ID. It is important that I only have one return ID because of how I'm implementing it. This is the code I tried first but I'm getting an error.
I did not try to add the exception of there being no 0s here because I thought it might be easier to add an If statement in the implementation of the method I use.
The error I get confuses me because It seems like I can't use FIRST when I thought I could, but here it is:
android.database.sqlite.SQLiteException: no such function: FIRST (code
1): , while compiling: SELECT FIRST (_id) FROM graph WHERE bac = 0;
My code:
public int getWhereZero(){
int zero = 0;
SQLiteDatabase db = getReadableDatabase();
String query = "SELECT FIRST (" + COLUMN_ID
+ ") FROM " + TABLE_GRAPH
+" WHERE " + COLUMN_BAC
+ " = 0;";
Cursor cursor = db.rawQuery(query, null);
if(cursor != null){
cursor.moveToFirst();
zero = cursor.getInt(cursor.getColumnIndex(COLUMN_ID));
cursor.close();
}
return zero;
}
SQLite doesn't have a FIRST() function. However, you can limit the number of rows returned to one using LIMIT, so sorting by the desired order will get the row you need:
SELECT column_id FROM graph ORDER BY bac LIMIT 1;

Why is SELECT COUNT (*) returning 1

Why is my getAccountCount only returning 1 when there are multiple entries in my database. Is this not the proper way to get the number of entries in my ACCOUNTS table?
getAccountCount
int getAccountCount() {
SQLiteDatabase db = this.getReadableDatabase();
Cursor cur = db.rawQuery("SELECT COUNT (*) FROM " + ACCOUNTS, null);
int x = cur.getCount();
cur.close();
return x;
}
Calling it from another activity
dbHelper = new DatabaseHelper(this);
txtNo.setText(String.valueOf(dbHelper.getAccountCount()));
Slightly embarrassed with my slip-up so here's an attempt to recover a little dignity ;_;.
In any case apologies for my mistake and thank you for the help. I'm fiddling with a tutorial code which had SELECT * FROM myTable originally but I read somewhere that using SELECT * in a large db could potentially affect performance as SELECT * gives the list of records with all columns from the table whereas SELECT COUNT * just counts the rows. But when I replaced SELECT * FROM myTable with SELECT COUNT (*) FROM myTable I forgot to change the interpretation of cur and just continued under the assumption that my getAccountCount() was fine.
Again, thank you for the help and criticism, both are appreciated. Cheers!
Why is my getAccountCount only returning 1 when there are multiple
entries in my database
Because Cursor.getCount() return number for rows in current cursor instead of count value.
To get COUNT value from cursor use Cursor.getInt with 0 position :
cur.moveToFirst();
int x = mcursor.getInt(0);
This will return nomber of entries in table
int numRows =(int) DatabaseUtils.queryNumEntries(db, "table_name");
You don't want getCount().
Even if the result of Select COUNT (*) is 5, getCOunt() will be 1...
you should rather do something like
if (cursor.moveToFirst()) // data?
System.out.println(cursor.getInt(0);

Select every nth term including first from sqlite database

I am trying to select the first row and every fifth one after that (this gives me 4 queries with unique rows) but I am not sure that it is correct as my results are not as expected.
//create the nth row selection
int n = level + 5;
//query the content resolver
Cursor cursor = contentResolver.query(
MainContentProvider.CONTENT_URI_ENGLISH,
DatabaseOpenHelper.PROJECTION_ENGLISH,
DatabaseOpenHelper.KEY_ROW_ID + " = " + (level+1) + " OR " + DatabaseOpenHelper.KEY_ROW_ID +" % " + n +" = 0",
null,
DatabaseOpenHelper.KEY_ROW_ID + " ASC"
);
where level is in [0,3] interval.
The results do not add up to the expected value, and are twice as less (approximately).
How should my query method look like to select every fifth row starting from the first one?
You can achieve this using query like (I'm not sure about it's performance though):
SELECT
id,
name,
(SELECT count(*) - 1 FROM my_table t_inner WHERE t.id >= t_inner.id) AS ordinal
FROM my_table t
WHERE ordinal % 5 == 0
ORDER BY id ASC;
Or you can create CursorWrapper which will return subset of rows. The downside of the this approach is that you'll have to fetch every row from the database, which might be slow if you have a lot of data.
(Assuming that the row IDs are consecutive,) rowid % X = 0 selects every Xth row, so you must not change X.
If you cannot change that term, you have to change another.
Either apply an offset to the rowid values ((rowid - offset) % X = 0), or compare against another value (rowid % X = offset), where offset is in the range from 0 to X-1.
Please note that the first comparison (rowid = level+1) is not necessary.

Error when accessing cursor elements

I'm trying to get all the IDs in the table by cursor. The table has 4 rows, and when I try to access the cursor by any index aside from 0 , the App crashes.
Guys, the problem still exists and even c.getInt(0) doesn't work...I really dont know where my mistake is???
the logcat also suggests that the error might be comes from
Toast.makeText(getApplicationContext(), "id="+dbd.getIDs()[0], Toast.LENGTH_SHORT).show();
I mean c.getint(0) returns the id, c.getint(2) returns error. Here is the code:
public int []getIDs() {
SQLiteDatabase db = this.getReadableDatabase();
SQLiteCursor c = (SQLiteCursor) db.rawQuery("SELECT " + BaseColumns._ID + " FROM Demo ", null);
int []r = new int[c.getCount()];
c.moveToFirst();
do{
r[c.getPosition()] = c.getInt(0);
}while(c.moveToNext());
c.close();
db.close();
return r;
}
Your select is a projection onto the ID column (select columns from ..., columns are the column ids you are interested in, and you specified just one). Thus the answer just has one column, namely the ID. Any access to columns with index > 0 will not work.
To access the other columns name them in the projection in your query.
c.getInt(0) return only value of first colunn from current row.
try this code:
do{
int r = c.getInt(0);
Log.d("Your class name","id value = "+r);
}while(c.moveToNext());
You can imagine Cursor as a table. There are rows and columns. And a cursor is pointing on a particular row in this table. Thus, to get all id's you should move across all rows.
c.getInt(ind) In this statement index is pointing on the column with index ind. Thus, in your code you try to get the second and third column and according to your code there is no these column.
To get a proper code you should create a loop and traverse all rows of your cursor. Also you should use c.getInt(0) to get the columns values.
Assuming you are selecting the appropriate Data, your problem is that you're not preparing the Cursor to be iterated.
Before iterating, call:
c.moveToFirst();
Like this:
int []r = new int [c.getCount()];
c.moveToFirst();
do{
r[c.getPosition()] = c.getInt(0);
}while(c.moveToNext());
c.close();
db.close();
return r;
This is well indicated in LogCat. I can't remember how it's put, but the message is very suggestive. Please post as much of the Log as possible, especially the good bits.
Also, I modified 'r' to be an array. As it was you were only returning the value of the last row.

How do I improve the performance of my SELECT query in Sqlite / Android?

I'm getting poor performance and possibly strange behavior with a simple SELECT query in Sqlite & Android. SqliteDatabase.query() executes my query in only 1 ms, but fetching the results with Cursor.get*() takes over 150 ms to return only 8 rows!
I am trying to find all the rows in the table english where the column word starts with "prefix" (an arbitrary string), sort the results by the row column, and return only the first 8 results.
Here is my code:
String columns[] = {"word", "rank"};
Cursor cursor = mDB.query("english", columns, "word LIKE '" + prefix + "%'", null, null, null, "rank,word", "8");
// It takes only 1 ms to get here
String word = "";
int rank = 0;
if (cursor.moveToFirst()){
do {
word = cursor.getString(0);
rank = cursor.getInt(1);
}
while(cursor.moveToNext());
}
cursor.close();
// It takes over 150 ms to get here!
The table definition for english is:
CREATE TABLE en (_id INTEGER PRIMARY KEY, word TEXT, rank INTEGER)
It contains about 65,000 entries. It also also indexes on word and rank, with a third index for both (I was getting desperate!):
CREATE INDEX "rank" ON "en" ("rank" ASC)
CREATE INDEX "word" ON "en" ("word" ASC)
CREATE INDEX "word_rank" ON "en" ("word" ASC, "rank" ASC)
Thanks in advance!
The query method doesn't actually retrieve all the data, the cursor retrieves it as it moves through the rows. So it makes sense that the Cursor.move*() methods are slower then the query.
This 'lazy-loading' concept helps save memory as only the relevant data is retrieved as it's needed.
As for performance, you really aren't doing anything wrong. Are you trying this on the emulator? Perhaps try it on an actual device and test the performance.

Categories

Resources