how can i decrement an int column of a SQLite table - java

I have a table in my data base that has three columns: Screen, Icon, and Rank: and i am trying to find the cleanest way to achieve the following..
i want to find all rows WHERE Screen = "myScreen" and Rank >5 // then make rank one less than current value.. I am doing this in Java via a SQLite Manager class in the following function:
public void DeleteScreenIcon (int id, String screenName, int rank){
int screenID = getScreenID(screenName);
SQLiteDatabase db=this.getWritableDatabase();
db.delete(isLookUp, colScreenID + "=" + screenID + " and " +colIconID+ "="+id, null);
// HERE IS WHERE I NOW WANT TO DO THAT..
db.execSQL("update "+ isLookUp +" set "+colRank+ "=" +colRank+ " -1 "+" where " + colScreenID + "='" +screenName + "' and " + colRank +">" +rank);
db.close();
}
sorry, im not that versed in SQL any help is appreciated

This update should do the trick:
UPDATE myTable
SET Rank = Rank - 1
WHERE Screen = "myScreen"
AND Rank > 5;

Related

How to retrieve Real type data from specific cell in android sqlite?

In this table, I want to retrieve the value 55.2 in a variable.
This value is at row 5 (ID=5) and in the column 'Weight' of type REAL.
I can already get the desired row number which is stored in 'lastID' and I know that my data is in the column 'Weight'. So I have my X and my Y in the table.
I also know the sqlite command to retrieve the 55.2 in my cursor:
Cursor cursor2 = db.rawQuery("SELECT Weight FROM <MYTABLE> WHERE ID=" + lastID, null);
Double lastWeight = cursor2.getDouble(0); //This line is wrong, I need the help here!
But I can't get the 55.2 value I am looking for in my variable lastWeight from cursor2.
Any idea?
Addendum
Here the create table:
String CREATE_TABLE2 = "CREATE TABLE " + <MYTABLE> + " (" + UID2 + " INTEGER PRIMARY KEY AUTOINCREMENT, " +
COL_2 + " TEXT," + COL_3 + " TEXT," + COL_4 + " REAL," + COL_5 + " REAL);";
db.execSQL(CREATE_TABLE2);
After the execution of this line:
Cursor cursor2 = db.rawQuery("SELECT Weight FROM <MYTABLE> WHERE ID=" + lastID, null);
you get the results in cursor2.
A Cursor instance like cursor2 is used to loop through its rows and to do so you must first place its index at the 1st row by moveToFirst():
if (cursor2.moveToFirst()) {
Double lastWeight = cursor2.getDouble(0);
........................................
}
The if statement is necessary just in case the cursor does not contain any rows.

How to get results from multiple local sql database tables?

I'm creating an app in android studio and i have some questions stored in a database which is created when the user opens the app for the first time and i created another database so the user can add his questions and i need to take a random question from out of these 2 databases.Each database have 3 same columns 1.question 2.heat 3.gender
Here's what i already tried but don't work.
public Cursor getQuestion(int HeatLevel, int Gender) {
SQLiteDatabase db = this.getWritableDatabase();
String query = "SELECT question, heat, gender FROM " + TABLE_NAME +
" WHERE heat = " + HeatLevel + " AND gender = " + Gender +
" UNION ALL" +
" SELECT question, heat, gender FROM " + SECOND_TABLE_NAME +
" WHERE heat = " + HeatLevel + " AND gender = " + Gender +
" ORDER BY RANDOM() LIMIT 1";
Cursor data = db.rawQuery(query, null);
return data;
}
So the app chooses a question from the database based on the difficulty and the players gender.
The above code produces an error saying "No such table" and the name of the second database like it can't find it.
i get the question in another activity using this
public void getQuestion(int HeatLevel, int Gender) {
Cursor question = QuestionDB.getQuestion(HeatLevel, Gender);
if (question.moveToNext()) {
QuestionTextView.setText(question.getString(0));
}
}
I'm new to sql so maybe the query is wrong.

Android : Calculate sum and group by month (SQLite)

Is there are any option to select amount, group them by month and calculate sum. I tried to get total sum of each month and pass it to ArrayList.
Example of data:
Amount Date
230 04/03/19
500 05/03/19
400 04/04/19
600 06/04/19
100 04/03/19
... ...
My code structure
private String CREATE_BILLS_TABLE = "CREATE TABLE " + TABLE_BILLS + "("
+ COLUMN_BILL_ID + " INTEGER PRIMARY KEY AUTOINCREMENT,"
+ COLUMN_BILL_USER_ID + " INTEGER,"
+ COLUMN_DESCRIPTION + " TEXT,"
+ COLUMN_AMOUNT + " INTEGER,"
+ COLUMN_DATE_STRING + " TEXT,"
+ COLUMN_COMPANY_NAME + " TEXT,"
+ COLUMN_CATEGORY + " TEXT,"
+ " FOREIGN KEY ("+COLUMN_BILL_USER_ID+") REFERENCES "+TABLE_USER+"("+COLUMN_USER_ID+"));";
public ArrayList<Bills> getDateByUserID(int userID){
SQLiteDatabase db = this.getReadableDatabase();
// sorting orders
ArrayList<Bills> listBillsDates = new ArrayList<Bills>();
Cursor cursor = db.query(TABLE_BILLS, new String[] { COLUMN_BILL_ID,
COLUMN_BILL_USER_ID, COLUMN_DESCRIPTION, COLUMN_AMOUNT, COLUMN_DATE_STRING, COLUMN_COMPANY_NAME, COLUMN_CATEGORY}, COLUMN_BILL_USER_ID + "=?",
new String[] { String.valueOf(userID) }, COLUMN_DATE_STRING, null, null, null);
if (cursor.moveToFirst()) {
do {
Bills bills = new Bills();
bills.setAmount(cursor.getInt(cursor.getColumnIndex(COLUMN_AMOUNT)));
bills.setDateString(cursor.getString(cursor.getColumnIndex(COLUMN_DATE_STRING)));
// Adding record to list
listBillsDates.add(bills);
} while (cursor.moveToNext());
}
cursor.close();
db.close();
// return category list
return listBillsDates;
}
I believe that a query based upon :-
SELECT sum(COLUMN_AMOUNT) AS Monthly_Total,substr(COLUMN_DATE_STRING,4) AS Month_and_Year
FROM TABLE_BILLS
WHERE COLUMN_BILL_USER_ID = 1
GROUP BY substr(COLUMN_DATE_STRING,4)
ORDER BY substr(COLUMN_DATE_STRING,7,2)||substr(COLUMN_DATE_STRING,4,2)
;
Note that other columns values would be arbritary results and as such cannot really be relied upon (fine if the data is always the same). Hence they have not been included.
Will produce the results that you want :-
e.g.
Using the following, to test the SQL :-
DROP TABLE IF EXISTS TABLE_BILLS;
CREATE TABLE IF NOT EXISTS TABLE_BILLS (
COLUMN_BILL_ID INTEGER PRIMARY KEY AUTOINCREMENT,
COLUMN_BILL_USER_ID INTEGER,
COLUMN_DESCRIPTION TEXT,
COLUMN_AMOUNT INTEGER,
COLUMN_DATE_STRING TEXT,
COLUMN_COMPANY_NAME TEXT,
COLUMN_CATEGORY TEXT)
;
-- Add the Testing data
INSERT INTO TABLE_BILLS (
COLUMN_BILL_USER_ID, COLUMN_DESCRIPTION, COLUMN_AMOUNT, COLUMN_DATE_STRING, COLUMN_COMPANY_NAME,COLUMN_CATEGORY)
VALUES
(1,'blah',230,'04/03/19','cmpny','category')
,(1,'blah',500,'05/03/19','cmpny','category')
,(1,'blah',400,'04/04/19','cmpny','category')
,(1,'blah',600,'06/04/19','cmpny','category')
,(1,'blah',100,'04/03/19','cmpny','category')
-- Extra data for another id to check exclusion
,(2,'blah',230,'04/03/19','cmpny','category')
,(2,'blah',500,'05/03/19','cmpny','category')
,(2,'blah',400,'04/04/19','cmpny','category')
,(2,'blah',600,'06/04/19','cmpny','category')
,(2,'blah',100,'04/03/19','cmpny','category')
;
SELECT sum(COLUMN_AMOUNT) AS Monthly_Total,substr(COLUMN_DATE_STRING,4) AS Month_and_Year
FROM TABLE_BILLS
WHERE COLUMN_BILL_USER_ID = 1
GROUP BY substr(COLUMN_DATE_STRING,4)
ORDER BY substr(COLUMN_DATE_STRING,7,2)||substr(COLUMN_DATE_STRING,4,2)
;
Results id :-
The above can then be converted for use by the SQLiteDatabase query method. So your method could be something like :-
public ArrayList<Bills> getDateByUserID(int userID) {
SQLiteDatabase db = this.getReadableDatabase();
String tmpcol_monthly_total = "Monthly_Total";
String tmpcol_month_year = "Month_and_Year";
String[] columns = new String[]{
"sum(" + COLUMN_AMOUNT + ") AS " + tmpcol_monthly_total,
"substr(" + COLUMN_DATE_STRING + ",4) AS " + tmpcol_month_year
};
String whereclause = COLUMN_BILL_USER_ID + "=?";
String[] whereargs = new String[]{String.valueOf(userID)};
String groupbyclause = "substr(" + COLUMN_DATE_STRING + ",4)";
String orderbyclause = "substr(" + COLUMN_DATE_STRING + ",7,2)||substr(" + COLUMN_DATE_STRING + ",4,2)";
ArrayList<Bills> listBillsDates = new ArrayList<Bills>();
Cursor cursor = db.query(TABLE_BILLS, columns, whereclause,
whereargs, groupbyclause, null, orderbyclause, null);
if (cursor.moveToFirst()) {
do {
Bills bills = new Bills();
bills.setAmount(cursor.getInt(cursor.getColumnIndex(tmpcol_monthly_total)));
bills.setDateString(cursor.getString(cursor.getColumnIndex(tmpcol_month_year))); //<<<<<<<<<< NOTE data is MM/YY (otherwise which date to use? considering result will be arbrirtaryy)
// Adding record to list
listBillsDates.add(bills);
} while (cursor.moveToNext());
}
cursor.close();
db.close();
// return category list
return listBillsDates;
}
The above has been tested and run and using the following code :-
ArrayList<Bills> myMonthlyTotals = mDBHelper.getDateByUserID(1);
Log.d("BILLSCOUNT","The number of bills extracted was " + String.valueOf(myMonthlyTotals.size()));
for (Bills b: myMonthlyTotals) {
Log.d("MONTHYLTOTAL","Monthly total for " + b.getDateString() + " was " + String.valueOf(b.getAmount()));
}
In an activity, resulted in the following in the log
:-
04-14 11:58:25.876 16653-16653/? D/BILLSCOUNT: The number of bills extracted was 2
04-14 11:58:25.877 16653-16653/? D/MONTHYLTOTAL: Monthly total for 03/19 was 830
04-14 11:58:25.877 16653-16653/? D/MONTHYLTOTAL: Monthly total for 04/19 was 1000
Please consider the comments in regard to values from non-aggreagted columns be arbitrary values. As per :-
Each non-aggregate expression in the result-set is evaluated once for an arbitrarily selected row of the dataset. The same arbitrarily selected row is used for each non-aggregate expression. Or, if the dataset contains zero rows, then each non-aggregate expression is evaluated against a row consisting entirely of NULL values. SELECT - 3. Generation of the set of result rows.
As per the comments, using recognised date formats can make the underlying SQL simpler and likely more efficient.

Making calculation from SQLite

I am trying to do two SQLite tables, one to enter data and another one to retrieve the calculated data.
First I want to let the client enter some REAL data and then calculate in the background and put the new data to the textview.
For now, I tried to retrieve it from one table.
#Override
public void onCreate(SQLiteDatabase db) {
String sSQL;
sSQL = "CREATE TABLE " + DataContract.TABLE_NAME +
"(" +
DataContract.Columns._ID + " INTEGER PRIMARY KEY NOT NULL, " +
DataContract.Columns.PRODUCT_NAME + " TEXT, " +
DataContract.Columns.PRODUCT_WIDTH + " REAL, " +
DataContract.Columns.PRODUCT_LENGHT+ " REAL, " +
DataContract.Columns.PRODUCT_PRICE+ " REAL, " +
//This is the data I want to calculate and put to a textview in a
//new intent
DataContract.Columns.PRODUCT_TOTAL_PRICE + " REAL)";
Log.d(TAG,sSQL);
db.execSQL(sSQL);
}
I have a Serializable class and I tried to calculate the data in this class.
private final String ProductName;
private final double ProductLenght;
private final double ProductWidth;
private final double ProductPrice;
private final double ProductTotalPrice;
Then I tried to calculate the data in getter method.
public double getProductTotalPrice() {
return (getProductWidth() * getProductLenght() * getProductPrice())/1000;
}
However, I dont know how to put retrieve the calculated data back to the textview.
Should I create two tables or one table is enough for this operation ?
And also what is the easiest way to calculate data inside Java code and put it back to a column ?
Thank you !
And also what is the easiest way to calculate data inside Java code
and put it back to a column ?
To do nothing (i.e. calculate the value when extracting the data and reduce the amount of data stored in the database)
To add another column for the calculated value would be a waste as you can calculate the value when extracting the data (into the cursor) e.g. :-
Assuming the table (called myproducts) is populated as follows (note no PRODUCT_TOTAL_PRICE column as it's not needed) :-
Then extracting it using the query :-
SELECT
_ID,
PRODUCT_NAME,
PRODUCT_WIDTH,
PRODUCT_LENGTH,
PRODUCT_PRICE,
(PRODUCT_WIDTH * PRODUCT_LENGTH * PRODUCT_PRICE)/1000 AS CALCULATED_TOTAL_PRICE
FROM myproducts;
Will result in :-
You could have a method in your Database Helper such as :-
public double Cursor getTotalpriceBtId(long id) {
double rv = 0;
String column_name = "totalprice";
String calculation = "(" +
DataContract.Columns.PRODUCT_WIDTH + " * " +
DataContract.Columns.PRODUCT_LENGHT + " * " +
DataContract.Columns.PRODUCT_PRICE + ")/1000";
String[] columns = new String[]{calculation + " AS " + column_name};
String whereclause = DataContract.Columns._ID + "=?";
String[] whereargs = new String[]{String.valueOf(id)};
Cursor csr = this.getWritableDatabase().query(
DataContract.TABLE_NAME,
columns,
whereclause,
whereargs,
null,null,null
);
if (csr.moveToFirst) {
rv = csr.getDouble(csr.getColumnIndex(column_name));
}
csr.close();
return rv;
}
The underlying SQL is similar to the example above. However, just the one column is needed.
However, I dont know how to put retrieve the calculated data back to
the textview.
Something along the lines of :-
yourTextView.setText(String.valueOf(yourDBHelperInstance.getTotalpriceBtId(ID_OF_THE PRODUCT)));
or perhaps :-
yourTextView.setText(String.valueOf(yourproduct.getProductTotalPrice()));
No need to create two tables
after inserting the value into table you just create a function by below query
select sum(your column name) from yourtablename where condition on which basis you filter the data.

Sqlite insert and update values of other columns

I have two tables; a 'parent' and a 'child' table. (not SQLite defitinions, just something i call them)
Everytime a child-object is created, it is assigned the value 0 in one of its columns.
When a new parent-object is created, every unassigned child-object, has to update the value mentioned before, to the parent-object's ID. My code looks like this:
public long createWorkout(String workoutName){
SQLiteDatabase db = this.getWritableDatabase();
ContentValues values = new ContentValues();
values.put(KEY_NAME, workoutName);
//Creates a new parent-object (a workout - the childs are exercises)
//the generated ID is returned as a long (workout_pk_id)
long workout_pk_id = db.insert(TABLE_WORKOUT, null, values);
//Selects all objects in the child-table with KEY_WORKOUT_ID = 0 (the column mentioned before)
String selectQuery = "SELECT * FROM " + TABLE_EXERCISE + " WHERE " + KEY_WORKOUT_ID + " == " + 0;
Cursor cursor = db.rawQuery(selectQuery, null);
//Takes each found object with value 0, and updates the value to the returned parent-ID from before.
if (cursor.moveToFirst()) {
do {
String k = "UPDATE " + TABLE_EXERCISE + " SET " + KEY_WORKOUT_ID + " == " + workout_pk_id;
db.execSQL(k);
} while (cursor.moveToNext());
}
return workout_pk_id;
}
But for some reason this doesn't work. The ID the childs/exercises remains 0. Can you help me?
I don't know if the error is somewhere in the setup of my tables, in that case i could provide some more information.
Thanks in advance. /Jeppe
EDIT: This is used in android, and I have debugged and verified that the workout_pk_id is returned, 45 objects are found in the selectQuery and yet it doesn't work. I also tried ContentValues to update the values, didn't work.
Edited the " == " to " = ", but the value is still not updated.
This is from eclipse - I've created a workout called "test", with the ID 160.
The exercise "test1" has the ID 430 (unique) but the workout_id is still 0.
It's been awhile since I did any Android stuff but I believe the "==" operator is incorrect:
String k = "UPDATE " + TABLE_EXERCISE + " SET " + KEY_WORKOUT_ID + " == " + workout_pk_id;
The operator you're using is a comparative operator, "=" is the assignment operator.
I also believe there is a better way to do what you are trying to do, currently refreshing my memory on Android so I'll get back to you. In the meantime tell me if replacing the operator works
Yeah so another way you can do this is by using subqueries. So it would look something like:
UPDATE TABLE_EXCERCISE SET KEY_WORKOUT_ID = WORKOUT_PK_ID WHERE KEY_WORKOUT_ID =
(
*subquery here to select parent object ids*
)
Here's a link to help:
http://www.tutorialspoint.com/sqlite/sqlite_sub_queries.htm
Let me know how this works for you.
I think you have to look to your update query.
It has to be:
String k = "UPDATE " + TABLE_EXERCISE + " SET " + KEY_WORKOUT_ID + " = " + workout_pk_id;
Look at the "=" between KEY_WORKOUT_ID and workout_pk_id.

Categories