I'm trying to retrieve the sum of a column from SQLITE. I am able to successfully get it.
But when I try to retrieve just the sum of 10 rows, it returns the sum of the entire column again. The query seems to be correct though.
public String getUnitsForWeek(Context context) throws IOException {
DataBaseHelper dbHelper = new DataBaseHelper(context);
String query = "SELECT sum(UNITS) FROM SERVICE_TABLE order by id DESC limit 7";
return String.valueOf(dbHelper.getString(query));
}
The dbHelper.getString method is:
public int getString(String query) {
String mypath = DB_PATH + DB_NAME;
SQLiteDatabase database = SQLiteDatabase.openDatabase(mypath, null,
SQLiteDatabase.OPEN_READWRITE);
Cursor cursor = null;
int i;
cursor = database.rawQuery(query, null);
cursor.moveToFirst();
i= cursor.getInt(cursor.getColumnIndex(cursor.getColumnName(0)));
return i;
}
Thanks.
SUM is an aggregate function that combines data from many rows into one. Since there is only one result row, LIMIT and ORDER BY are meaningless.
To sum UNITS on the 7 rows with highest ID, you can use a subselect:
SELECT SUM(UNITS) FROM (SELECT UNITS FROM SERVICE_TABLE ORDER BY id DESC LIMIT 7);
Can't you do a subelect?
SELECT sum(UNITS) FROM (SELECT UNITS FROM SERVICE_TABLE order by id DESC limit 7) s
Related
I have to make more than 300 selects from my database.
Each of those queries has to be called inside of a for each loop, here's an example:
for(int id : myids){
Cursor cursor = MyDatabaseHelper.runMyQuery(id);
while(cursor.moveToNext()){
//my stuff...
}
}
MyDatabaseHelper is an instance of a database helper class, the function is like this
public Cursor runMyQuery(int id){
SQLiteDatabase db = this.getWritableDatabase();
Cursor ret = db.rawQuery("select Name, Surname, Age from PTable where Id = " + id, null);
return ret;
}
I've been told that the constant "open and close" of the db because of multiple queries it the cause of my performance issues and I should, instead, make a single query (using union etc).
Changing my code to a single query would mean changing the entire database, and I was hoping not to do that.
Is there anything I can do to improve the performance and keep the multiple selects at the same time?
Thanks
I think what you are looking for is the in clause.
Convert your myids into a string. Something like
String inClause = "(1,2,3)"
and you can use it as
"select Name, Surname, Age from PTable where Id in " + inClause
You can read more of the in operator here
You can return a single Cursor containing all the rows.
First change your runMyQuery() method to this:
public Cursor runAll(String list){
SQLiteDatabase db = this.getWritableDatabase();
String sql = "select Name, Surname, Age from PTable where " + list + " like '%,' || id || ',%'"
Cursor ret = db.rawQuery(sql, null);
return ret;
}
So you pass to the method runAll() a String which is the the comma separated list of all the ids that you have in myids and with th eoperator LIKE you compare it to each id of the table.
You create this list and get the results in a Cursor object like this:
StringBuilder sb = new StringBuilder(",");
for(int id : myids){
sb.append(String.valueOf(id)).append(",");
}
String list = sb.length() > 1 ? sb.toString() : "";
if (list.length() > 0) {
Cursor c = runAll(list);
while(c.moveToNext()){
//your stuff...
}
}
I am developing an application where the user inputs title and the date. I want to prevent the duplicated titles being inputted on the same day in to database. I am checking if the title exists on the selected date. However my query seems not to work and i don't know why, the application just crashes.Is this query correct? Can someone help?
public boolean checkExist(String title, String date) {
SQLiteDatabase db = this.getWritableDatabase();
Cursor c = db.rawQuery("SELECT * FROM "+TABLE_NAME+" WHERE "+TITLE+"=?" +"AND" + DATE+"=?", new String[] {title,date});
boolean exists = c.moveToFirst();
c.close();
return exists;
}
One issue that you have is that c.moveToFirst will always fail if a match does not exist as you are trying to move to a row in an empty cursor.
The resolution is to not use c.moveToFirst and instead get the count of the rows and then set the return value accordingly.
e.g.
public boolean checkExist(String title, String date) {
SQLiteDatabase db = this.getWritableDatabase();
Cursor c = db.rawQuery("SELECT * FROM "+TABLE_NAME+" WHERE "+TITLE+"=?" +"AND" + DATE+"=?", new String[] {title,date});
boolean exists = c.getCount() > 0;
c.close();
return exists;
}
The second issue is that the query itself is wrong as you do not have spaces either side of the AND keyword. That is instead of
Cursor c = db.rawQuery("SELECT * FROM "+TABLE_NAME+" WHERE "+TITLE+"=?" +"AND" + DATE+"=?", new String[] {title,date});
You should have
Cursor c = db.rawQuery("SELECT * FROM "+TABLE_NAME+" WHERE "+TITLE+"=?" +" AND " + DATE+"=?", new String[] {title,date});
Personally, I setup constants for SQL keywords that include the space and then use these. So I'd have something along the lines of +TITLE+"=?" + SQLAND + DATE+"=?". Where SQLAND would be defined along the lines of String SQLAND=" AND ";
PS look at Cricket_007's answer, the code is neater/better it's easier to read.
Your spacing is off. TITLE+"=?" +"AND" + DATE becomes TITLE=?ANDDATE=?
I would suggest this. See DatabaseUtils.queryNumEntries
public boolean checkExist(String title, String date) {
SQLiteDatabase db = getReadableDatabase();
String[] args = new String[] {title,date};
String filter = String.format("%s=? AND %s=?", TITLE, DATE);
return DatabaseUtils.queryNumEntries(db, TABLE_NAME, filter, args) > 0;
}
you should be using c.getCount() instead of c.moveToFirst()
if the value is greater than 0, then it exists
I'm currently writing an app which allows you to pick a category, and the app will retrieve all results in that category and print them onto the screen. The code for the creation of the database is fine, but I am unsure on whether my retrieval method is correct, and then totally unsure as to how I would print out the individual names of the results into a TextView.
Currently, I have:
public Cursor getDatabase(int category)
{
String myPath = DB_PATH + DB_NAME;
myData = SQLiteDatabase.openDatabase(myPath, null, SQLiteDatabase.OPEN_READONLY);
Cursor cur;
cur=myData.rawQuery("select * from youthcentres where cat1='"+category+"' OR cat2 ='"+category+"' OR cat3='"+category+"'",null);
cur.moveToFirst();
myData.close();
return cur;
};
You now need to retrieve the data from the cursor using the appropriate getter methods.
For example, say you retrieved the following from the database:
1. Name (text) 2. Age (integer)
So, when you want to retrieve them from the cursor, you will go as follows:
String name = cur.getString(0);
int age = cur.getInt(1);
Remember that the zero-index is relative to the search query and not the table.
You may have columns in the table as (name,address,class,age) in which case age is at index 3. That doesn't matter to the cursor here :)
I have large number of strings, approximately 15,000 that I stored in a SQLite database using the following code:
void addKey(String key, String value, String table) {
SQLiteDatabase db = this.getWritableDatabase();
ContentValues values = new ContentValues();
values.put(KEY_KEY, key); // Contact Name
values.put(KEY_VALUE, value); // Contact Phone
// Inserting Row
db.insert(table, null, values);
db.close(); // Closing database connection
}
And then i search through that database using the following method in order to pick out any strings that match the key im looking for:
public String searchKeyString(String key, String table){
String rtn = "";
Log.d("searchKeyString",table);
// Select All Query
String selectQuery = "SELECT * FROM " + table;
SQLiteDatabase db = this.getWritableDatabase();
Cursor cursor = db.rawQuery(selectQuery, null);
// looping through all rows and adding to list
if (cursor.moveToFirst()) {
do {
Log.d("searchKeyString","searching");
if(cursor.getString(1).equals(key))
rtn = rtn + "," + cursor.getString(2);
} while (cursor.moveToNext());
}
cursor.close();
db.close();
Log.d("searchKeyString","finish search");
return rtn;
}
The goal is to do this in real time as the user is typing on the keep board so response time is key and the way it stands now it takes over a second to run through the search.
I considered reading all of the items into an array list initially and sorting through that which might be faster, but i thought an array list of that size might cause memory issues. What is the best way to search through these entries in my database?
A couple of things you can do...
Change the return to a StringBuilder until the end.
Only use a readable version of the database (that's probably not making much difference though)
Do not get a new instance of the database every time, keep it opened until you don't need it anymore
Query for only what you need with the "WHERE" argument in the SQL query.
See the code below with some changes:
// move this somewhere else in your Activity or such
SQLiteDatabase db = this.getReadableDatabase();
public String searchKeyString(String key, String table){
StringBuilder rtn = new StringBuilder();
Log.d("searchKeyString",table);
// Select All Query
String selectQuery = "SELECT * FROM " + table + " WHERE KEY_KEY=?";
Cursor cursor = db.rawQuery(selectQuery, new String[] {key});
// you can change it to
// db.rawQuery("SELECT * FROM "+table+" WHERE KEY_KEY LIKE ?", new String[] {key+"%"});
// if you want to get everything starting with that key value
// looping through all rows and adding to list
if (cursor.moveToFirst()) {
do {
Log.d("searchKeyString","searching");
rtn.append(",").append(cursor.getString(2));
} while (cursor.moveToNext());
}
cursor.close();
Log.d("searchKeyString","finish search");
return rtn.toString();
}
Note even if you want this to happen in "real-time" for the user, you will still need to move this to a separate Thread or ASyncTask or you are going to run into problems....
You should consider using SELECT * FROM your-table LIMIT 50, for example. And you can put two buttons "Back", "Next" on your view. If every page has max 50 items, the user is at page 1, and he taps "Next", then you can use this query:
SELECT * FROM your-table LIMIT 50 OFFSET 50
If your table contains most of text-data, and you want to integrate search deeply into your app, consider using virtual table with FTS.
Let sqlite do the hard lifting.
First off, add an index to the field you're searching for, if you don't have one already. Secondly, don't do a SELECT all with manual table scan, but rather use a query in the form
SELECT column_value
FROM my_table
WHERE column_key LIKE "ABC%"
This returns the least amount of data, and the sql engine uses the index.
i dunno about better but maybe it'd be faster to make queries for the selected strings one by one.
public String searchKeyString(String key, String table){
String rtn = "";
Log.d("searchKeyString",table);
// Select All Query
String selectQuery = "SELECT * FROM " + table + "WHERE column_1 = " + key;
SQLiteDatabase db = this.getWritableDatabase();
Cursor cursor = db.rawQuery(selectQuery, null);
// looping through all rows and adding to list
if (cursor.moveToFirst()) {
rtn = rtn + "," + cursor.getString(2);
}
cursor.close();
db.close();
Log.d("searchKeyString","finish search");
return rtn;
}
EDIT:
Well i dunno how those custom keyboard apps do it, but those AutoCompleteTextViews are hooked up to adapters. you could just as easily make a cursorAdapter and hook your auto-complete view to it.
http://www.outofwhatbox.com/blog/2010/11/android-autocompletetextview-sqlite-and-dependent-fields/
http://www.opgenorth.net/blog/2011/09/06/using-autocompletetextview-and-simplecursoradapter-2/
hi I have a SQLite Database and I've placed it in my assets folder. I was wondering how you can "print" information from the table on the screen. I have looked around and all I can find are people adding to a database all I want to do is show it on the screen and add some filters later on.
It should be roughly like this:
private static String DB_PATH = "/data/data/com.your.app/your_path/yourdb.sqlite";
private static SQLiteDatabase myDataBase;
public static void openDatabase() {
String queryString="YOUR SQL QUERY HERE";
myDataBase = SQLiteDatabase.openDatabase(DB_PATH, null,SQLiteDatabase.OPEN_READONLY);
Cursor cursor = myDataBase.rawQuery(queryString, null);
if(cursor!=null) {
cursor.moveToFirst();
while(!cursor.isLast()) {
/*CHECK CURSOR USAGE AND DO SOMETHING WITH YOUR RESULTS HERE */
cursor.moveToNext();
}
}
myDataBase.close();
}
I think this may help.
Retrieve data from the SQLIte database and store them in a String / Strings.
Bring in some TextViews in your xml to your layout.
get references to those textview / textviews in your java code.
textview.settext(-----the string retrieved------);
This will print whatever string that your retrieved from your SQLite database.
SQLiteDatabase database;
public int getId() {
String sqlQuery = "SELECT * FROM <table_name>;
int id = 0;
Cursor cursor = database.rawQuery(sqlQuery, null);
if (cursor.moveToFirst()) {
id = cursor.getInt(0); // In my case, id (int) is in first column
}
return id;
}