I've got two tables
Workout Table
Workout_ID --------- Workout Name
1 --------------------------- Chest
2 ---------------------------- Back
Date of Workouts Table
Date_ID------- Date of Workout------ Workout_ID
1-----------------------22/12/13---------------- 1
2---------------------- 23/12/13---------------- 2
Within android, using MySqlite currently:
i have these exact tables.
However when i come to OUTPUT my 'Date of Workouts Table' onto the screen, what MySQLite Code will i need to do so? General points would be really appreciated.
Somehow i need to take the 'Workout_ID' and compare it to the 'Workout_ID' in the Workout Table and generate 'Chest' and then output that
EDIT Here i've got my code which Outputs whe Workout_ID which is present in the Date of Workouts Table
public String getWorkoutNameInfo() {
// TODO Auto-generated method stub
String[] columns = new String[] { KEY_DATE_OF_WORKOUT,
KEY_WORKOUT_NAME, KEY_DATE };
Cursor c = ourDatabase.query(TABLE_DATE_WORKOUT, columns, null, null,
null, null, null, null);
String workoutName2 = "";
int iWorkoutID = c.getColumnIndex(KEY_WORKOUT_NAME);
for (c.moveToFirst(); !c.isAfterLast(); c.moveToNext()) {
workoutName2 = workoutName2 + c.getString(iWorkoutID);
}
System.out.println(workoutName2);
return workoutName2;
}
HERE I'm trying to query my WorkoutTable WHERE my workout_id is equal to the workoutSlectedNameInfo
So i'm trying to go down the list of Workout_ID in my 'Date of Workouts Table' and compare the 1 and 2 to the Workout Table - This doesn't work - Will this Join statement allow me to do this?
public String test(String workoutSelectedNameInfo) {
// TODO Auto-generated method stub
String Weight = "";
open();
ourDatabase = ourhelper.getReadableDatabase();
Cursor c = ourDatabase
.rawQuery(
"SELECT workout_name FROM WorkoutTable WHERE workout_id = ?",
new String[] { workoutSelectedNameInfo });
int iWeight = c.getColumnIndex(KEY_WORKOUT_NAME);
for (c.moveToFirst(); !c.isAfterLast(); c.moveToNext()) {
Weight = Weight + c.getString(iWeight) + "\n";
}
c.close();
ourDatabase.close();
return Weight;
// TODO Auto-generated method stub
}
here db proper innitialised instance
String sql = "select workoutname from WorkoutTable as wt,WorkoutDayTable wdt where wt.Workout_ID = wdt.Workout_ID ";
Cursor cursor = db.rawQuery(sql,null);
The query
SELECT * FROM Workout LEFT JOIN DateofWorkout ON (Workout.Workkout_ID = DateofWorkout.Workout_ID) WHERE Workout.Workout_ID = "??????" -- use your ID to find the data
------------------------------------------------------------------
There are three basic JOINS
The CROSS JOIN
The INNER JOIN
The OUTER JOIN
Plus read this simple guide you really need, anyhow just read the GUIDE, after reading you won't ask question regarding queries anymore
Tutorial About SQLite and Android
Edited
dbHelper = new DbHelper(this);
SQLiteDatabase db = dbHelper.getReadableDatabase();
Cursor c = db.db.rawQuery("SELECT * FROM Workout LEFT JOIN DateofWorkout ON Workout.Workkout_ID = DateofWorkout.Workout_ID", null);
while(c.moveToNext())
{
// your code goes here
}
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 am new on android development. I have a table with 9 columns who can store products , first is _id autoincrement, and the other two last insertdays and days.
In insertdays i store current date as integer after convert date to int. In the days column i store the number of days to expire a product.
I made 3 methods getDays(), getInsertdate(), expCheck().
The getDays return to expCheck the days for each row, its working
The getInsertdate return to expCheck the inserted date its working
The problem is, when i try to update my database , expCheck() called on onCreate() and onResume() methods, the values of days column for all rows(products) does not updated. With expCheck() method i try to reduce the number of days for each day who pass.
My database table in the photo the last column must reduce by one if pass one day, reduce by 2 each row if pass two days e.t.c ... Can anyone help me !!!
public int getInsertDate(int productId){
int output=0;
SQLiteDatabase db = mDbHelper.getReadableDatabase();
String[] projectionG = {
ProductEntry.COLUMN_PRODUCT_INSERTDATE};
Cursor cursor1 = db.query(TABLE_NAME, projectionG, " _id = ?", new String[] {String.valueOf(productId) }, null, null, null, null);
if (cursor1 !=null) {
if (cursor1.moveToFirst()) output = cursor1.getInt(7);
}
cursor1.close();
return output;
}
public int getDays(int productId){
int output=0;
SQLiteDatabase db = mDbHelper.getReadableDatabase();
String[] projectionD = {ProductEntry.COLUMN_PRODUCT_DAYS};
Cursor cursor = db.query(TABLE_NAME, projectionD, " _id = ?", new String[] {String.valueOf(productId) }, null, null, null, null);
if (cursor !=null) {
if (cursor.moveToFirst() ) {
output = cursor.getInt(8);
}
}
cursor.close();
return output;
}
public void expCheck(){
//Read current date
Calendar calendar = Calendar.getInstance();
SQLiteDatabase db=mDbHelper.getWritableDatabase();
// Define a projection that specifies which columns from the database
// you will actually use after this query.
String[] projection = {
ProductEntry.COLUMN_PRODUCT_DAYS
};
// Perform a query on the products table
Cursor cursor = db.query(
ProductEntry.TABLE_NAME, // The table to query
projection, // The columns to return
null, // The columns for the WHERE clause
null, // The values for the WHERE clause
null, // Don't group the rows
null, // Don't filter by row groups
null); // The sort order
int j = toJulianDate(calendar.getTime());
Toast.makeText(this, "date is" + j,Toast.LENGTH_SHORT).show();
//Method getInsertDate return the insert date of product to database
int currentInsertdate = getInsertDate(cursor.getColumnIndex(ProductEntry.COLUMN_PRODUCT_INSERTDATE));
// Method getDays return the number of days to expire a product
int currentDays = getDays(cursor.getColumnIndex(ProductEntry.COLUMN_PRODUCT_DAYS));
currentDays = currentDays - (j - currentInsertdate);// calculate the new amount of remaining days to expire th product
ContentValues values = new ContentValues();
values.put(ProductEntry.COLUMN_PRODUCT_DAYS, currentDays);
//update all rows
db.update(TABLE_NAME, values, null, null);
}
http://postimg.org/image/4vozphdk7/
So these are my tables;
I save my data in such a way that the Workout_ID (second figure) references the Workout_ID in the top figure.
What i need - How can i 'Look up' what Workout_ID 2 is and output the string, when it comes to displaying my table?
Done in SQLite, is this possible?
Coded Table column Names:
date_id = date_of_workout_id
date = date_of_workout
workout_name = workout_name
date_of_workout = DateofWorkout
workout_table = WorkoutTable
workout_id(date's one) = name_of_workout
workout_id(WorkoutTables's one) = workout_id
public String test(String WorkoutSelectedNameInfo) {
// TODO Auto-generated method stub
String Weight = "";
open();
ourDatabase = ourhelper.getReadableDatabase();
Cursor c = ourDatabase.rawQuery("SELECT date_of_workout_id,
date_of_workout, workout_name FROM DateofWorkout JOIN WorkoutTable ON
DateofWorkout.name_of_workout = WorkoutTable.workout_id", null);
int iWeight = c.getColumnIndex(KEY_WORKOUT_NAME);
while(c.moveToNext())
{
Weight = Weight + c.getString(iWeight) + "\n";
}
c.close();
ourDatabase.close();
System.out.println(Weight);
return Weight;
}
A very simple JOIN can do that;
SELECT date_id, date, workout_name
FROM date_of_workout
JOIN workout_table
ON date_of_workout.workout_id = workout_table.workout_id
SELECT date_ID, date, workout_name
FROM workouts, dates
WHERE workouts.workout_ID = dates.workout_ID
Updated Answer:
Try changing
Cursor c = ourDatabase.rawQuery("SELECT date_of_workout_id,
date_of_workout, workout_name FROM DateofWorkout JOIN WorkoutTable ON
DateofWorkout.name_of_workout = WorkoutTable.workout_id", null);
to
Cursor c = ourDatabase.rawQuery("SELECT date_of_workout_id,
date_of_workout, workout_name FROM DateofWorkout JOIN WorkoutTable ON
DateofWorkout.workout_id = WorkoutTable.workout_id", null);
the problem maybe is because you are comparing name_of_workout from workout_id.
A simple inner join perhaps?
select dow.date_id, dow.date, w.name
from workout w, date_of_workout dow
where w.workout_id = dow.workout_id
I'm trying a simple SQL Command wihtin my Android-App, to get the age of a selected Person:
public int getAge(){
SQLiteDatabase db = this.getReadableDatabase();
Cursor cursor = db.rawQuery("SELECT * FROM persons WHERE name =? " + MainActivity.selectedPerson.getText().toString(), null);
int age = cursor.getInt(3); // column with ages
cursor.close();
db.close();
return age;
}
But when I run my app, it crashes when I call the function getAge(). I get the following Error:
SQLiteException: no such column: Max: , while compiling: SELECT * FROM persons WHERE name = Max
I don't get it. There is the name "Max" in the table. What am I doing wrong? Thanks in advance.
Edit 2:
With this one:
Cursor cursor = db.rawQuery("SELECT name FROM persons WHERE name = '" + MainActivity.selectedPerson.getText().toString() + "'", null);
I get a different error:
08-27 19:43:47.573: E/AndroidRuntime(6161): android.database.CursorIndexOutOfBoundsException: Index -1 requested, with a size of 1
what does this mean?
You should consider using the selectionArgs parameter of rawQuery() to prevent SQL Injection Attacks:
Cursor cursor = db.rawQuery("SELECT * FROM persons WHERE name = ?", new String[] { MainActivity.selectedPerson.getText().toString() });
Also you only need one column so rather than wasting resources by selecting them all with *, you should just select the one column:
Cursor cursor = db.rawQuery("SELECT age FROM persons WHERE name = ?", new String[] { MainActivity.selectedPerson.getText().toString() });
Hope that helps!
All together it should look like:
public int getAge(){
SQLiteDatabase db = this.getReadableDatabase();
Cursor cursor = db.rawQuery("SELECT age FROM persons WHERE name = ?", new String[] { MainActivity.selectedPerson.getText().toString() });
int age;
// Check if you have a valid result and move to the first row to read it
if(cursor.moveToFirst())
age = cursor.getInt(0);
// Prevent a crash if there is no data for this name
else
age = 0;
cursor.close();
db.close();
return age;
}
Chan ge the 3rd line of your program:
Cursor cursor = db.rawQuery("SELECT * FROM persons WHERE name =? " + MainActivity.selectedPerson.getText().toString(), null);
to this:
Cursor cursor = db.rawQuery("SELECT * FROM persons WHERE name = ?", new String[] { MainActivity.selectedPerson.getText().toString()} );
Try this:
public int getAge(){
int age;
SQLiteDatabase db = this.getReadableDatabase();
Cursor cursor = db.rawQuery("SELECT * FROM persons WHERE name = '" + MainActivity.selectedPerson.getText().toString()+"'",null);
if(cursor.moveToFirst())
{
age = cursor.getInt(3); // column with ages
}
cursor.close();
db.close();
return age;
}
You missed the single quotes (' ') in your sql command. That's why MAX was taken as a column and not as a value.