I made a SQLite highscores that has 3 columns; rank(int), score(long) and percentage(int). I am trying to pull all the data from the columns and compare them to the score the user just got to see if their new score made the highscores list that holds the top 10.
I want the highscores to be prioritized by percentage first and then score to break any ties. Below is where I am starting to do this. Am I on the correct track? I have never used SQLite even outside of Java so this is all brand new to me.
Thank you in advance for your help.
//Check if new record makes the top 10.
public boolean check(int rank, long score, int percentage) {
//SQL query to get last score/percentage if highscores has 10 records...
long[] scores = new long[9];
int[] percentages = new int[9];
scores = db.execSQL("SELECT " + SCORE + " FROM " + TABLE + ";"); //Error: Type mismatch
percentages = db.execSQL("SELECT " + PERCENTAGE + " FROM " + TABLE + ";"); //Error: Type mismatch
//Algorithms to compare scores and percentages go here...
}
scores = db.execSQL("SELECT " + SCORE + " FROM " + TABLE + ";");
execSQL returns void.
As per javadoc
Execute a single SQL statement that is NOT a SELECT or any other SQL statement that returns data.
You may need to use either query (or) rawQuery mechanisms to do select.
Related
Hi I currently have a database that has 5 questions and answers stored in it. I want to randomly output three of the questions each time the app runs. I have the below code but my app crashes when it loads
public List<Question> getAllQuestions() {
List<Question> quesList = new ArrayList<Question>();
int nQuestions = 3; //select COUNT(*) from questions
Random random = new Random();
int id = random.nextInt(nQuestions);
String selectQuery = "SELECT id FROM " + TABLE_QUEST;
dbase=this.getReadableDatabase();
Cursor cursor = dbase.rawQuery(selectQuery, null);
// looping through all rows and adding to list
if (cursor.moveToFirst()) {
do {
Question quest = new Question();
quest.setID(cursor.getInt(0));
quest.setQUESTION(cursor.getString(1));
quest.setANSWER(cursor.getString(2));
quest.setOPTA(cursor.getString(3));
quest.setOPTB(cursor.getString(4));
quest.setOPTC(cursor.getString(5));
quesList.add(quest);
} while (cursor.moveToNext());{
id = random.nextInt(nQuestions);
}
}
// return quest list
return quesList;
}
Sorry that I write this as an answer, but I don't have permissions to write comments to a question, so I want to tell you that first of all you will always become one of the first 3 added questions as a random question, because for the random id you use as limitations 3 id = random.nextInt(nQuestions); instead of nQuestions (which is 3 for you, you should use questList.size() and do it 3 times for the numbers from 0 to questList.size()
The issue is, you are only selected the id from the table, for all entries.
Your random will also select only questions 0, 1 or 2. Your random should be random.nextInt(5) since you have 5 questions.
Finally, this should be in a loop and then add multiple wheres to your query to get multiple questions.
String query = "SELECT * FROM " + TABLE_QUEST + " WHERE ";
for (int x = 0; x < nQuestions; x++) {
if (x > 0) {
query += " OR ";
}
query += "id=" + random.nextInt(5);
}
This will make your query look like this:
SELECT * FROM TABLE_QUEST WHERE id=4 OR id=2 OR id=3
Finally, change the way your cursor.moveToNext() is. Your code should look something like this:
public List<Question> getAllQuestions() {
List<Question> quesList = new ArrayList<Question>();
int nQuestions = 3; //select COUNT(*) from questions
Random random = new Random();
String query = "SELECT * FROM " + TABLE_QUEST + " WHERE ";
for (int x = 0; x < nQuestions; x++) {
if (x > 0) {
query += " OR ";
}
query += "id=" + random.nextInt(5);
}
dbase=this.getReadableDatabase();
Cursor cursor = dbase.rawQuery(query, null);
// looping through all rows and adding to list
if (cursor.moveToFirst()) {
do {
Question quest = new Question();
quest.setID(cursor.getInt(0));
quest.setQUESTION(cursor.getString(1));
quest.setANSWER(cursor.getString(2));
quest.setOPTA(cursor.getString(3));
quest.setOPTB(cursor.getString(4));
quest.setOPTC(cursor.getString(5));
quesList.add(quest);
} while (cursor.moveToNext());
}
// return quest list
return quesList;
}
There are a couple of mistakes in your code.
First, your SQL query is wrong:
String selectQuery = "SELECT id FROM " + TABLE_QUEST;
gives you all the values of the "id" column in the table TABLE_QUEST, not the column with the id you determined with your call to Random.nextInt.
String selectQuery = "SELECT * FROM " + TABLE_QUEST + " WHERE id=" + id;
The "*" stands for "all columns in this table" and the "WHERE" enables you to filter your rows according to the conditions that follow (i.e. id=3).
Note while it's not a problem in this case, passing unescaped values (i.e., the WHERE id=" + id part is very bad form because it might make you vulnerable to SQL injections as soon as you use user input for this).
Second: the rest of the code doesn't make much sense for various reasons. I'll try to list a few:
if your code would work (i.e. with * instead of id in the SELECT, but without the WHERE clause), you'd just add all of the questions in your database to the list, because there's no condition.
if the condition would work, you'd get just one row with a certain id. your do-while loop would run only once.
if you had a loop around the select, then it might work, but it'd probably return the same rows TWICE or even more often.
you'd still get occasional crashes for various reasons, among them
primary keys - the id attribute which is probably auto-increment - is not necessarily in the range 0..n-1. it might be in your case, but that's not exactly typical. auto-incrementing primary keys usually start at 1.
if your question-answers records are CRUD (create, read, update, delete), the ids might have holes, i.e. "1, 2, 6, 8, 12".
i'd rewrite the whole method; there are a couple of ways of doing it. just a few hints:
if there are very few records in the table (e.g. less than a couple hundreds) you can just load all the questions into list A.
create list A
add all records from the database to list A
create a list B
as long as there are fewer elements in list B than you want (i.e. listB.size() < 3) remove a random element from List A and add it to List B.
return listB. // this seems wasteful, but would probably be ok in your case.
let the database do the randomizing:
SELECT * FROM table ORDER BY RANDOM() LIMIT 3;
read all the records into a list
return the list
done! (note: this works with sqlite, but is, as far as i know, not universally accepted by different database systems).
there are countless other ways of achieving your goal. but i'd just use the ORDER BY RANDOM() LIMIT x trick, it's probably the easiest way.
I want to get all the "Amount" value total of specific account number into a double or into a vector. Because of my database having many transactions for same account number i can't figure out how to get total value of all the records.My code giving me the last transaction amount value only not the sum of all. Appreciate any help
ResultSet rs5 = (ResultSet) st1.executeQuery("SELECT Amount FROM Incoming_Transactions WHERE AccountNumber LIKE '" + accountnum+ "%'");
while (rs5.next()) {
Vector <Double> em = new Vector();
em.add(rs5.getDouble("Amount"));
Double [] myArray = em.toArray(new Double[0]);
check2 = myArray[0];
}
If you just want the sum of all the amounts, and don't care about individual amounts, you can get it directly from executing the SQL query :
SELECT SUM(Amount) FROM Incoming_Transactions WHERE AccountNumber LIKE '" + accountnum+ "%'"
If you to fetch the individual amounts for the given account and calculate the sum yourself, you can iterate over the myArray array or em Vector and add all the amounts. If you choose this approach, move the initialization of em outside the loop.
Every iteration of your while loop, you are resetting your Vector<Double> em. That means only the most recent element actually ends up in your loop. Fix this by moving the declaration of your Vector outside the loop like so
Vector <Double> em = new Vector();
ResultSet rs5 = (ResultSet) st1.executeQuery("SELECT Amount FROM Incoming_Transactions WHERE AccountNumber LIKE '" + accountnum+ "%'");
while (rs5.next()) {
em.add(rs5.getDouble("Amount"));
}
Double [] myArray = new Double[em.size()];
myArray = em.ToArray(myArray);
//Now do stuff with all the entries
If you only are interested in the sum, you can move the sum into the query itself like Eran suggests, or declare a sum variable outside the loop and update it every loop like this:
Double runningSum = 0.0;
ResultSet rs5 = (ResultSet) st1.executeQuery("SELECT Amount FROM Incoming_Transactions WHERE AccountNumber LIKE '" + accountnum+ "%'");
while (rs5.next()) {
runningSum += rs5.getDouble("Amount");
}
Below query will return account number and respective sum of amount
Select accountnumber,sum(amount) from Incoming_Transactions WHERE AccountNumber LIKE '" + accountnum+ "%' group by accountnumber
Also, if you don't want to modify query you can use map wherein accountnumer is key and value will be amount. If you already have account number in map add amount into current amount value otherwise add new account into map
total in this case is 500. Trying to make a calculator, but not everything's adding up. It seems to skip the multiplication and just display total*amount. Is there something I'm doing wrong? EDIT: Discount: in the example, .92. I get 455000 if amount is 1000.
if (wShipping==true){
if (GroundShipping.isSelected()){
if (amount<=99) {
shipping=1.05;
output.setText(output.getText() + amount + "\t" + total*1.05*amount*discount + "\n");
}
else{
output.setText(output.getText() + amount + "\t" + total*amount*discount + "\n");
}
}
if (AirShipping.isSelected()){
shipping=1.1;
output.setText(output.getText() + amount + "\t" + total*amount*1.1*discount + "\n");
}
if (FedexShipping.isSelected()){
shipping=1.25;
output.setText(output.getText() + amount + "\t" + (total*amount*discount)*(1.25) + "\n");
}
}
You should consider the following things--
1) Why is the variable shipping needed if you are directly using the value in the set statement
2) Use else if statement since all the options are exclusive
3) You might want to check the initial values for variables and the formula for calculating the price. Taking the initial values as given, the lowest possible price is-
Price = 1000*500*0.92 = 460000 (total x amount x discount)
Hence there must be something amiss with your initial values
Maybe, just maybe is the first rule of currency calculations:
why not use double or float to represent currency
I am using real type to save price value in SQLite database but it does not return correctly value. If I save a few values like 1.01 it will return 4.029999999999999.
I have read that best way to save prices in SQLite is to use integer type
But I don't know how to use it.
How to store and retrieve prices in this case?
Here code how I retrieve price now:
Cursor cursor = null;
double totalPrice = 0;
try {
cursor = mDB.rawQuery("select " + Expense.PRICE + " from " + Expense.TABLE_NAME + " where " + " (strftime("
+ dateType + ", " + Expense.DATE + "))" + "= ? ", new String[] { currentDate });
} catch (Exception e) {
Log.e(TAG, "error" + e.toString());
e.printStackTrace();
}
for (cursor.moveToFirst(); !cursor.isAfterLast(); cursor.moveToNext()) {
totalPrice += cursor.getDouble(cursor.getColumnIndex(Expense.PRICE));
}
It is actually quite simple when you see it.
I don't know what currency you are in, but assume US $.
You want to store $1.01. This is the same as 101 cents. You just multiply by 100.
So before storing the number, multiply by 100.
When displaying the number, divide by 100.
Just to add to that answer: I also think you should store the numbers in memory as cents/integers too. So for all your workings, calculations etc, use that integer format.
If a user enters a $ amount, convert it straight away into integer (multiply by 100). And only change back to $ when you need to display it.
In other words, not just when going to and from the database.
Effective Java book describes, in Item 48, that one should not use float or double if exact answers is required.
I think you should use long value to store the price value, but store the values in "cents" (or equivalent as per currency of choice) instead of "dollars". This way your math around prices should work just fine with no loss due to floating-point arithmetic.
So im trying to count how many rows and columns an input file of a completed sudoku board has. I've come up with this loop
public static Pair<Integer, Integer> rowColumnCount(Scanner input1){
int nrows=0;
int ncolumns=0;
while(input1.hasNextLine()){
while(input1.hasNextInt()){
input1.nextInt();
ncolumns++;
}
input1.nextLine();
nrows++;
}
System.out.print("Rows: " +nrows + "\n");
System.out.print("Columns: " +ncolumns + "\n");
return new Pair<Integer, Integer>(nrows, ncolumns);
}//end rowCoulmnCount
I got the idea to make this method from a previous method I have in which I read and created an array of the sudoku board input file. I figured the two methods would be similar, but they're not.. the outpuut of nrws and ncolumns is 1 & 81. So could someone help me figure out the proper way to count columns to make sure there are 9. Or would it be better to start comparing the values of the rows and columns to see if there are any duplicates (of 1-9) in use that error checking to see if there are the correct number of rows and columns?
try:
public static Pair<Integer, Integer> rowColumnCount(Scanner input1){
int nrows=0;
int ncolumns=0;
while(input1.hasNextLine()){
Scanner subinput1 = new Scanner(input1.nextLine());
while(subinput1.hasNextInt()){
subinput1.nextInt();
ncolumns++;
}
nrows++;
}
System.out.print("Rows: " +nrows + "\n");
System.out.print("Columns: " +ncolumns + "\n");
return new Pair<Integer, Integer>(nrows, ncolumns);
}//end rowCoulmnCount