Android SQLite get youngest person from database - android

I have a Person object that I store in a SQLite database.
Person has Age, FirstName, and LastName.
At a given moment, I want to find the youngest person (lowest Age).
How can I do this?
So far I have this:
public Person getYoungest(Cursor c) {
c.moveToFirst();
db.rawQuery("SELECT MIN(" + AGE + ") FROM " + PERSON_TABLE, null);
// Person youngestPerson = ???
// return youngestPerson;
}
However, I'm really confused at what the "rawQuery" does. It doesn't return a person object. Also, I'm not sure whether the query gives me the lowest "age", or the record containing the lowest "age" (which is what I want). I'm very new to SQL, so this is all strange to me.
Any advice?

What you are currently doing is querying for smallest age value from your dataset. If you want to get the whole data row of such you need to use ORDER BY, like
SELECT * FROM ... ORDER BY age ASC LIMIT 1
which would sort the data by Age in ascending order. As you want just one we use LIMIT to ensure this is going that way (and to make things faster), yet note that most likely many records may have the same age (incl. lowest value) so you may extend ORDER BY to fine tune sorting.

SQLite returns strings, numbers, byte arrays.
They are not like java-objects. You have to retrieve your each value and initialize your person in the code using a constructor.
Or use realm database that easily helps to store java-objects using sqlite.
do not forget to improve the performance by using
SELECT * FROM ... LIMIT 1
like Marcin Orlowski said.
to retrieve the data use this:
if (c.moveToFirst()) {
int idColIndex = c.getColumnIndex("id");
int nameColIndex = c.getColumnIndex("name");
int emailColIndex = c.getColumnIndex("email");
int id = c.getInt(idColIndex)
String name = c.getString(nameColIndex)
String email = c.getString(emailColIndex)
to create an object use this:
new Person(<your values>);

db.rawQuery ==> return a Cursor which point to the returned data from select statement so you should make
Cursor cursor = db.rawQuery("SELECT * FROM PERSON_TABLE ORDER BY age ASC , null);
if(cursor.moveToFirst()) //mean find data and point to the samllest
cursor.getString(c.getColumnIndex("field_name"));

Related

Why does the rawquery in my sqlite database give me the wrong person?

I made an app in eclipse for android where you can fill in a person's information like name, email, adress, etc. In this app I need to include a search-button, which will search for a person that is saved in the database when one or more pieces of information are known. E.g. when I only remember the email-adress of a person who is saved in the database, I need to be able to find that person by searching for a matching email. This is the code I used for doing so:
public Person getPerson(String naam, String adres, String email, String geslacht,
String leeftijd, String geboortedatum){
SQLiteDatabase db= this.getReadableDatabase();
Cursor curs=db.rawQuery("SELECT * FROM personen WHERE name = ? OR adress = ? "
+ "OR email = ? OR gender = ? OR age = ? OR birthday = ?",
new String[]{naam==null?"'":naam, adres==null?"'":adres,
email==null?"'":email, geslacht==null?"'":geslacht,
leeftijd==null?"'":leeftijd, geboortedatum==null?"'":geboortedatum});
if(curs!=null)
curs.moveToFirst();
The reason I changed the args[] when it included a null-value is that otherwise the rawQuery won't work. This code however, does not return the person I was searching for, but it simply returns the very first person in the database.
When simplifying the code by making the query search for a persons name only it actually does return the person with that name:
Cursor curs=db.rawQuery("SELECT * FROM personen WHERE name = ?", new String[]{naam});
if(curs!=null)
curs.moveToFirst();
What is wrong with the first rawQuery and why doesn't it return the person I'm looking for, but simply the first person in the database, whereas the second rawQuery does return the right person?
I guess the problem is with the OR. Could you try AND and see ? Because OR is usually means optional. What i mean by optional is, you are telling sql engine to return the person with any of those attributes it matches too. So you are not restricting but giving many possibility abd OR is ending up with many users and therefore its getting the first one. Dont use OR. Try creating a query that returns a unique result you want.
public Person getPerson(String naam, String adres, String email, String geslacht,
String leeftijd, String geboortedatum){
SQLiteDatabase db= this.getReadableDatabase();
Cursor curs=db.rawQuery("SELECT * FROM personen WHERE name = ? OR adress = ? "
+ "OR email = ? OR gender = ? OR age = ? OR birthday = ?",
new String[]{naam==null?"'":naam, adres==null?"'":adres,
email==null?"'":email, geslacht==null?"'":geslacht,
leeftijd==null?"'":leeftijd, geboortedatum==null?"'":geboortedatum});
if(curs!=null)
if (curs.moveToFirst()){
while(curs.hasNext){
//Your code, this will return all the rows of your sql,use curs.next() to get a row
}

SQLite get row data using SELECT

Using SQLite Database, I have a table with 6 columns in each row as the rows are added. The first column is the name of the "person." I have it so when you click on the person in a listview, it brings up a screen with 5 edit texts. You fill them out and submit it and it adds it to another row in the database.
To retrieve that data later on, I am trying to use SELECT by the name to get it, but cannot figure out how this works.
public Cursor getChildRulesInformation(DatabaseOperations dop, String name) {
dop.getReadableDatabase().execSQL("SELECT * FROM "+CHILD_RULES_TABLE_NAME+" WHERE "+CHILD_NAME + "=\""+ name+"\"");
}
What do I do with that to retreive every column inside of that specific row. I am confused on the process to get it out.
Any lead in the write direction would be greatly appreciated. Thanks. If you need any more information please let me know.
Try this,
public Cursor getChildRulesInformation(DatabaseOperations dop, String name) {
return dop.getReadableDatabase().rawQuery("SELECT * FROM "+CHILD_RULES_TABLE_NAME+" WHERE "+CHILD_NAME+" = '"+ name+"' ", null);}
Do not use execSql for getting data, that is only for sending data to the database. Instead, use rawQuery if you want to use the String. So it would be:
public Cursor getChildRulesInformation(DatabaseOperations dop, String name) {
return dop.getReadableDatabase().rawQuery("SELECT * FROM "+CHILD_RULES_TABLE_NAME+" WHERE "+CHILD_NAME + "='"+ name+"'", null);
}
This will return you the cursor object that you are looking for.

Sort values in child views of custom listview android

I designing a custom ListView ,which has more child view
I have ideas about sorting the ListViewdata in "Asc" or "Desc" order ,that retrieves data directly from database , but in my case I used CustomSimpleCursorAdapter , I requires to sort data in TextView depending upon the values that is:
today
tomorrow
more than 2 days i.e; 354
CustomSimpleCursorAdapter .java
//Days remaining for BirthDay
String year=cursor.getString(cursor.getColumnIndex(BirthdayProvider.EVENT_YEAR));
String month=cursor.getString(cursor.getColumnIndex(BirthdayProvider.EVENT_MONTH));
String date=cursor.getString(cursor.getColumnIndex(BirthdayProvider.EVENT_DATE));
String remainingDays=BirthdayCalculation.getDaysRemainingForNextBirthDay(year, month, date);
Calendar today=Calendar.getInstance();
int CMonth=(today.get(Calendar.MONDAY)+1);
int CDate=(today.get(Calendar.DAY_OF_MONTH));
//checking whether the BD is on TODAY
if (remainingDays.equals("1") && (CDate==Integer.parseInt(date) && (CMonth)==Integer.parseInt(month))) {
viewHolder.txtDaysRemainigValue.setTextSize(TypedValue.COMPLEX_UNIT_SP, 20);
viewHolder.txtDaysRemainigValue.setTypeface(fontRoboto_Regular);
viewHolder.txtDaysRemainigValue.setTextColor(Color.parseColor("#00CC33"));
remainingDays="today";
}
//checking whether the BD is on TOMORROW
else if (remainingDays.equals("1")) {
viewHolder.txtDaysRemainigValue.setTextSize(TypedValue.COMPLEX_UNIT_SP, 17);
viewHolder.txtDaysRemainigValue.setTextColor(Color.parseColor("#FF0099"));
remainingDays="tomorrow";
viewHolder.txtDaysRemainigValue.setTypeface(fontRoboto_Regular);
}
//checking how many days remaining BD
else{
remainingDays=BirthdayCalculation.getDaysRemainingForNextBirthDay(year, month, date);
viewHolder.txtDaysRemainigValue.setTextSize(TypedValue.COMPLEX_UNIT_SP, 27);
viewHolder.txtDaysRemainigValue.setTextColor(Color.parseColor("#990000"));
}
Here's Screen Shot link
When you query your database, you should use an "order by" clause. For example, this method takes the order by clause as the last argument. I don't know how you store your dates and times in your database, but if it's something SQLite can recognize and provide sorting on, then it should work. The following will query for all columns on a table named "table" with no where clause, no "group by" clause, no "having" clause, and order by the time column descending (use ASC for ascending if you want that instead):
database.query("table", null, null, null, null, null, "time DESC");
EDIT
If you can't store the exact data you want (in this case days remaining until an event), I can only see two options:
1). After getting the cursor, you iterate over the results and compose a new sorted list. You could make some kind of model object in java, read the values into it from the cursor, and sort them with a comparator function. At that point you probably would not use a CursorAdapter any more. It's quite easy to build your own ListAdapter - I recommend you watch The World of Listview
2). Since the query methods take strings, you can actually compose more complicated queries so that SQLite provides you the data you DO want (and still sort it for you as well). If your times are stored as longs, you could do something like this:
long currentTime = System.currentTimeMillis();
String timeAsString = Long.toString(currentTime);
String remainingTimeColumn = "(time_column - " + timeAsString + ") AS remaining_time";
// compose query
String table = "table";
String[] columns = new String[] {"column1", "column2", ..., "columnN", remainingTimeColumn};
String order = "remaining_time ASC";
// query
Cursor cursor = database.query(table, columns, null, null, null, null, order);
// later, get remaining time from cursor row
long remainingTime = cursor.getLong(cursor.getColumnIndex("remaining_time"));
In this case "time_column" is the name of the column that stores the event time. What this is doing is creating an additional column with the name "remaining_time", which is calculated from one of the actual column values. The results are then sorted by that synthesized column. The cursor you get back will contain this column and these values, you just need to have the proper column name to access them.
Since I don't know the details of your data format, I can't say this is exactly how your query should look, but the idea should be clear. You can work out the finer details from here...
If you get the data in database, you can use ASC or DESC and put ArrayList.
another way is you can use Collections.sort(). but you must data class implements comparable and overriding compare method.

Selecting range of dates from sqlite database

i am trying to select some accounts depending on the updating time..
My Table named as account and has columns like createdOn , updatedOn, acountName etc.
Now the date is being stored as string 2012-03-20
How can i make sql query to select diff accounts depending on date.
Here is my code
public ArrayList<Account> getAllAccountsForReports(Date dateTo, Date dateFrom)
{
ArrayList<Account> accounts = new ArrayList<Account>();
String queryString = "SELECT * FROM MAAccounts WHERE updatedOn = ? BETWEEN updatedOn = ? ORDER BY accountType, accountName";
Cursor result = mDb.rawQuery(queryString, new String[]{ dateToDB(dateTo), dateToDB(dateFrom)});
Please tell me how can i correct my sql query.
Best Regards
Your BETWEENsyntax is off, what you want is probably;
SELECT * FROM MAAccounts
WHERE updatedOn
BETWEEN ? AND ?
ORDER BY accountType, accountName
Since you're storing by 'yyyy-MM-dd', between should work well using a string.
I wasn't sure what table name to use since you said it was called account in the question and MAAccounts in the code and the columns are mis-spelled in the question, so of course you need to adapt it to your actual column names.

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