Android: Delete all sqlite rows NOT IN top 5 - java

I have a database for my leaderboard. Currently, I insert all scores into my leaderboard, and select the 5 highest scores to show on my app. I think it would take up too much room to never delete the other scores, so I would like to delete them. How can I do this?
Here's how I select the top 5 scores, ranked first by score and second by time if score is equal:
public Cursor gethmLeaderboard(SQLiteDatabase db){
String[] columns = {TableInfo.LB_RANK, TableInfo.LB_SCORE, TableInfo.LB_TIME};
Cursor c = db.query(TableInfo.TABLE_HM, null, null, null, null, null, TableInfo.LB_SCORE + " DESC, " + TableInfo.LB_TIME + " ASC", "5");
return c;
}
Here's how I create my table:
public String CREATE_HMQUERY = "CREATE TABLE " + TableInfo.TABLE_HM + "("
+ TableInfo.LB_RANK + " INTEGER PRIMARY KEY AUTOINCREMENT DEFAULT 1 ," + TableInfo.LB_SCORE +
" INT,"+ TableInfo.LB_TIME + " VARCHAR );";
I want to delete all rows NOT IN that query. How can I do that?
Edit:
I tried this query:
public String DEL_ALLBUTES = "DELETE FROM " +
TableInfo.TABLE_HM + " WHERE " +
TableInfo.LB_RANK + " NOT IN (SELECT " +
TableInfo.LB_RANK + " FROM " +
TableInfo.TABLE_HM + " ORDER BY " +
TableInfo.LB_SCORE + " DESC, " +
TableInfo.LB_TIME + " ASC LIMIT 5);";
In this format:
db.rawQuery(DEL_ALLBUTES, null);
But when I check the database there are still tons of rows so it doesn't work.

Your table needs to have some unique ID. Use that to identify the rows you want to keep:
DELETE FROM ES
WHERE ID NOT IN (SELECT ID
FROM ES
ORDER BY Score DESC, Time ASC
LIMIT 5);

You can create temp table insert top 5 score into temp table and delete all table then insert temp table into main table.
CREATE TEMP TABLE TempES AS SELECT
ID
FROM
ES
ORDER BY
Score DESC,
Time ASC
LIMIT 5;
DELETE
FROM
ES;
INSERT INTO ES SELECT
*
FROM
TempES;
DROP TABLE TempES;

Related

Error no such column in SQLite when updating rows

I'm trying to update data in rows in my DB, but i catch error that there's no such column (no such column 'Moscow' or another)
This is DBHelper code:
public static final String tableName = "currentWeather";
public static final String KEY_ID = "_id";
public static final String cityName = "city";
public static final String cityTemp = "temperature";
And creating DB:
sqLiteDatabase.execSQL("create table " + tableName + "(" + KEY_ID + "
integer primary key autoincrement,"
+ cityName + " text," + cityTemp + " text, " + " UNIQUE(" + cityName +
"))");
and error shows when i try to execSQl in response:
sqLiteDatabase.execSQL(
"UPDATE " + DBHelper.tableName + " SET " +
DBHelper.cityTemp + "=" +
response.body().getForecastMain().getTemp() + "
WHERE "
+ DBHelper.cityName + "=" + cityName);
I expect to update temperature data in rows by cityName
cityName and response.body().getForecastMain().getTemp() are strings and they should be passed surrounded with single quotes to the sql statement:
sqLiteDatabase.execSQL(
"UPDATE " + DBHelper.tableName + " SET " + DBHelper.cityTemp + "='" + response.body().getForecastMain().getTemp() + "'" +
"WHERE " + DBHelper.cityName + " = '" + cityName + "'"
);
But the recommended and safe way of doing the update is with the use of ContentValues and ? as placeholders for the parameters:
ContentValues cv = new ContentValues();
cv.put(DBHelper.cityTemp, String.valueOf(response.body().getForecastMain().getTemp()));
int rows = sqLiteDatabase.update(
DBHelper.tableName,
cv,
DBHelper.cityName + " = ?",
new String[] {cityName}
);
You can examine the value of the integer variable rows.
If it is 1 this means that 1 row was updated (because cityName is unique) so the update was successful.
I think you have changed column name or add new one (city). So you can fix it by two ways
By uninstall the application from phone
Add column name in upgrade method.
Example:
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
// If you need to add a column
if (newVersion > oldVersion) {
db.execSQL("ALTER TABLE foo ADD COLUMN new_column INTEGER DEFAULT 0");
}
}
The thing is you need to wrap the values after the = sign in single quotations in the UPDATE statement. As for digits they work in both cases.
For example here is the correct syntax
UPDATE currentWeather
SET temperature = 45
WHERE
city = 'Moscow'
But in your code I'm assuming cityName has the value Moscow without the single quotation marks so the converted SQL code will be like this
UPDATE currentWeather
SET temperature = 45
WHERE
city = Moscow
Now the sql interpreter will think Moscow is some database object or column or something and not a literal value. So you need to surround your values in single quotation marks.
Also consider What the data type of response.body().getForecastMain().getTemp() is.
If it's int you have to parse it or something, as the data type of the related column is Text.

Issue deleting row from SQL Table

I'm trying to remove a row from an SQL table using this code below. However, whenever I call this method I get this following error:
android.database.sqlite.SQLiteException: no such column: Plumber (code 1): , while compiling: DELETE FROM service WHERE name = Plumber
public boolean deleteService(String name){
SQLiteDatabase db = this.getWritableDatabase();
boolean result = false;
String query = "SELECT * FROM "
+ TABLE_SERVICE
+ " WHERE "
+ COLUMN_NAME
+ " = \""
+ name
+ "\""
;
Cursor cursor = db.rawQuery(query, null);
if(cursor.moveToFirst()){
String nameStr = cursor.getString(0);
db.delete(TABLE_SERVICE, COLUMN_NAME + " = " + nameStr, null);
cursor.close();
result = true;
}
db.close();
return result;
}
This is my table
public void onCreate(SQLiteDatabase db){
String CREATE_USERS_TABLE = "CREATE TABLE " +
TABLE_SERVICE + "("
+
COLUMN_NAME + " TEXT," +
COLUMN_RATE + " TEXT," +
COLUMN_CATEGORY + " TEXT," + COLUMN_SUBCATEGORY + " TEXT)";
db.execSQL(CREATE_USERS_TABLE);
}
First you're fetching all the rows that in COLUMN_NAME have the value name.
Next you want to delete the 1st of these rows (maybe it's the only one?) because nameStr gets the value of the 1st column which is COLUMN_NAME.
Why are you doing this?
Just execute this statement:
int number = db.delete(TABLE_SERVICE, COLUMN_NAME + " = '" + name + "'", null);
if number gets the value 0 then no rows were deleted, else it gets the number of deleted rows.
delete deletes rows not columns.
If you want to get rid of a column, you need to drop it. The SQL syntax is:
alter table table_service drop column <column_name>;
I don't know how to express this in java with the methods that you are using.
Ensure that your SQL syntax is correct, and that "Plumber" is a string with double quotes. By my experience, these errors are usually caused by an incorrect column or name.
Use this format:
DELETE FROM table_name WHERE condition(s)
SQLite browser can also help you visualize your database.

misuse of aggregate function SUM()

I want to insert the SUM of Somme_versee (column in table Versement) in the column Versement_total.
This is a part of my code:
statement.executeUpdate("INSERT INTO Versement ( Nom , Prenom, Date , Somme_versee,Prix_du_logement, Nom_du_projet) VALUES('" + nom.getText() +"','" +prenom.getText() +"','" +date.getText() + "'," + verse.getText() + ", " + "(SELECT Prix_du_logement FROM Client WHERE Nom='"+ nom.getText() +"' AND Prenom='"+ prenom.getText() + "')," + " (SELECT Nom_du_projet FROM Client WHERE Nom='" + nom.getText()+ "' AND Prenom='" +prenom.getText() + "'))");
statement.executeUpdate("UPDATE Versement SET Versement_total= SUM(Somme_versee) " );
When executing I get this error: misuse of aggregate function SUM()
You should never do this in the same table. And it will get worse when the table gets more records. But what you seem to want is:
UPDATE Versement SET Versement_total = (SELECT SUM(Somme_versee) FROM Versement)

Sqlite Android Optimization

I have an application that works well. But I suspect that I can improve it if I optimize queries to the database. And I need suggestions.
This is part of my "select query":
private static final String SELECT = "SELECT " +
"dz.first_id AS first_id, " +
"dz._id AS _id, " +
"dz.att1 AS att1, " +
"dz.att2 AS att2, " +
"dz.att3 AS att3, " +
"dz.att4 AS att4, " +
"dz.att5 AS att5, " +
"d.var1 AS var1, " +
"d.name AS name, " +
"d.last_update AS last_update, " +
"d.image_url AS image_url, " +
"d.image_highlighted_url AS image_highlighted_url, " +
"d.var2 AS var2, " +
"d.type AS type, " +
"d.state AS state, " +
"d.sync AS sync, " +
"d.var3 AS var3 " +
"FROM table1 dz INNER JOIN table2 d " +
"ON d._id = dz.first_id ";
Cursor result = conn.rawQuery(SELECT, null);
*table1 and table2 have simple creation: only one _id integer PRIMARY KEY AUTOINCREMENT NOT NULL
It is useful to use views? Any other suggestion?
Thanks.
This query looks as cut and dry and they can get, I think your options are really either to see if you can somehow leave some unnecessary columns out of your select or alternatively to see that both dz.first_id and d._id have indexes setup. Perhaps add a index to dz with the following
CREATE INDEX index1 ON table1 (first_id);

How to give priority to one table in Sqlite

I have two tables. In those tables, my stop id might be in one of them or both of them. If my stop id doesnt exist in B, it should pick from A. And if it doesnt exist in A, it should pick from B. And if stop id exist in both tables then I want to give priority to B and retrieve the row from B. Below query always returns the value from B. Can you help me out to fix this?
String selectQuery = "SELECT "
+ stop_id + ","
+ name + ","
+ latitude + ","
+ longitude + ","
+"1 as "+priority
+" FROM "+ A
+" UNION SELECT "
+ stop_id + ","
+ name + ","
+ latitude + ","
+ longitude + ","
+"2 as "+priority
+" FROM "+ B
+" WHERE " + stop_id + " =? "
+" ORDER BY "+priority
+" LIMIT 1 ";
Cursor cursor = db.rawQuery(selectQuery, new String[] {id});
In your UNION ALL you should apply the WHERE clause to both SELECTs; your current code applies the condition to only the B side, while the A side returns all rows. LIMIT 1 at the end hides this problem, though.
String concatenation does not make it easy to see, but you should be passing id twice, and using two ? placeholders in your query:
SELECT stop_id, name, latitude, longitude, 1 as priority
FROM A
WHERE stop_id = ?
UNION ALL
SELECT stop_id, name, latitude, longitude, 2 as priority
FROM B
WHERE stop_id = ?
ORDER BY priority DESC
LIMIT 1

Categories

Resources