Is there a simpler way to group and present data from an SQLite database than what I'm about to propose? If so, how would you improve it?
In an app I'm doing for a gym, I need to be able to record the history for 5 types of exercise classes, by date, in descending order (newest on top). In the spirit of sharing code to better understand, here is my table creation:
private static final String CREATE_TABLE_BJJ = "CREATE TABLE IF NOT EXISTS "
// TODO finish this
+ TABLE_BJJ + "(" + COLUMN_ID + " INTEGER PRIMARY KEY AUTOINCREMENT, "
+ BJJ_HISTORY_MOVE + " TEXT NOT NULL, " + BJJ_HISTORY_MOVECOUNT + " INTEGER NOT NULL, "
+ BJJ_HISTORY_PERFORMEDBY + " TEXT NOT NULL, " + BJJ_HISTORY_PERFORMEDTO
+ " TEXT NOT NULL, " + DATE + " datetime NOT NULL, " + UPLOADED
+ " INTEGER NOT NULL DEFAULT 0);";
this results in something like this once data gets recorded:
for the history page though, I need to somehow group all moves performed by date into one row with a sum of the number of moves performed, as in the screenshot below:
What I was thinking might work would be to populate an array with the results of a SELECT DISTINCT STATEMENT then filling an array with the results like so:
String query ="SELECT DISTINCT Date FROM BJJHistory";
ArrayList<String> dateList = new ArrayList<String>();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
Cursor cursor = database.rawQuery(query,null);
if (cursor != null) {
cursor.moveToFirst();
if (!cursor.isAfterLast())
{
do
{
String datestr = sdf.format(new Date(cursor.getString(0)));
dateList.add(datestr);
}
while (cursor.moveToNext());
}
}
return cursor;
I have a custom class to hold the results:
Public class History {
public String numMoves;
public String date;
public History() {
super();
}
public History(final String numMoves, final String date) {
super();
this.numMoves = numMoves;
this.date = date;
}
}
Afterward, using the array to then create cursors to pull data back as such:
final ArrayList<History> BJJHistory = new ArrayList<History>();
for (int i = 0; dateList.size(); i++) {
final Cursor cursor = db.rawQuery("SELECT COUNT(*) FROM BJJHistory WHERE Date LIKE '" + dateList(i).toString() + "%'") > 0, null);
if (cursor != null) {
cursor.moveToFirst();
BJJHistory.add(new History(cursor.getString(0).toString(),dateList[i].toString()))
}
lot of typing
Finally, using an array adapter to fill the listview with the resulting arraylist of history items. I would still need to use a way to implement an onclick listener that would query the database for all the items for each date, so the user could see what moves they did that date, but the main listview is more important right now.
As always, Thanks in advance!
The GROUP BY clause does what you want; the date function also helps:
SELECT COUNT(*), date("Date") FROM BJHistory GROUP BY date("Date")
I ended up getting it to work with a slightly modified version of what I posted above. For anyone interested, here's my code (which could probably be improved upon):
First, I get all the unique dates from the table:
public String[] getUniqueDates(final String tablename) {
final String query = "SELECT DISTINCT Date FROM " + tablename
+ " ORDER BY Date DESC";
final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
final SimpleDateFormat sourceFormat = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
final Cursor cursor = database.rawQuery(query, null);
String datestr = null;
final Set<String> set = new LinkedHashSet<String>();
if (cursor != null) {
cursor.moveToFirst();
if (!cursor.isAfterLast()) {
do {
// Convert the date to YYYY-MM-DD
try {
final Date dt = sourceFormat.parse(cursor.getString(0));
datestr = sdf.format(dt);
} catch (final ParseException e) {
e.printStackTrace();
}
set.add(datestr);
} while (cursor.moveToNext());
}
cursor.close();
}
return set.toArray(new String[0]);
}
Then I have a class in my Database Access class that selects the number of dates matching the date:
public String selectCount(final String date) {
String count = "";
final Cursor cursor = database.rawQuery("SELECT COUNT(*) FROM "
+ SQLiteHelper.TABLE_BJJ + " WHERE Date LIKE '" + date
+ "%'", null);
if (cursor != null) {
cursor.moveToFirst();
count = cursor.getString(0);
cursor.close();
}
return count;
}
The meat and potatoes that puts the data into the ListView:
String[] DateArray = datasource.getUniqueDates(SQLiteHelper.TABLE_BJJ);
final History BJJHistoryArray[] = new History[DateArray.length];
for (int i = 0; i < DateArray.length; i++) {
String suffix;
if (datasource.selectCount(DateArray[i]).equals("1"))
suffix = " Move";
else
suffix = " Moves";
BJJHistoryArray[i] = new History(datasource.selectCount(DateArray[i]) + suffix,
DateArray[i]);
}
final HistoryAdapter adapter = new HistoryAdapter(this, R.layout.history_row,
BJJHistoryArray);
BJJHistory.setAdapter(adapter);
This results in the following:
When a new entry is logged with the log entry button, it refreshes the query, thus changing the number up by 1 each time.
Things to improve:
Add a parameter for the selectCount() method, so that it can be used on any table.
Try to optimize cursors, if possible.
Optimize code, if possible.
Related
I would to like to display data from a local database table according to a user condition.
Code to display:
public void viewContact(){
String name = getIntent().getStringExtra("name").toString();
tvName.setText(name);
String phone = db.getContacts(name).toString();
tvPhone.setText(phone);
String web = db.getContacts(name.toString();
tvWeb.setText(web);
}
DBHelper.class:
public Cursor getContacts(String therapist_name){
String selectQuery = " SELECT therapist_phone, therapist_web " +
" FROM " + THERAPIST_TABLE + " WHERE " + THERA_NAME + " = " + "'" + therapist_name + "'";
SQLiteDatabase db = this.getReadableDatabase();
Cursor cursor = db.rawQuery(selectQuery, null);
return cursor;
}
Can anyone point out where I've gone wrong?
Explanation:
The activity receives contact name from previous activity (hence getIntent()). Then with that, it would like to view data from database relating to the contact and thus would like to view the phone_number and website columns.
So if therapist_name is equal that of selected contact from previous activity, it would only display the therapist_number and therapist_website of that contact in the next activity.
You should have an Object Contact with the properties you want, and everytime you run the query, go trough the steps Ana said of checking if the cursor is null and moving to first (i personally check the size of the cursor also, to Log an error if is empty).
And then return the created object, so when you call the method, you have everything there, something like this:
public List<Contact> getContacts(String therapist_name){
List<Contact> listOfContacts = new ArrayList<>();
String selectQuery = " SELECT therapist_phone, therapist_web " +
" FROM " + THERAPIST_TABLE + " WHERE " + THERA_NAME + " = " + "'" + therapist_name + "'";
SQLiteDatabase db = this.getReadableDatabase();
Cursor cursor = db.rawQuery(selectQuery, null);
if (cursor != null) {
if (cursor.moveToFirst()) {
do {
//Save data in variables here
String ph_no = cursor.getString(0); // therapist contact
String web = cursor.getString(1); //therapist web
listOfContacts.add(new Contact(ph_no, web));
} while (cursor.moveToNext());
}
}
return listOfContacts;
}
This returns a list of objects, just in case there is more than one match. You can tweak it to get one, or the first match, and return just the Contact object, so you would have your data,
You are just returning cursor object. Read the data and then return the retrieved data.
Example:
Cursor cursor = db.rawQuery(selectQuery, null);
if (cursor != null) {
if (cursor.moveToFirst()) {
do {
//Save data in variables here
ph_no = cursor.getString(0); // therapist contact
web = cursor.getString(1); //therapist web
} while (cursor.moveToNext());
}
}
//pass an array of ph_no and web from here now
I want to create a android sqlite table with only one single row, for insert or update and read, how can i do that, cause i only know how to create mulitiple row
the table contain only 1 single row , is for user insert data and store , when read the data will come out , and last the update mean it will override the data which in that row.
this is my DBHelperNote.java
public static final String TABLE_GOAL = "goal";
public static final String GOAL_ID= "goal_id";
public static final String GENDER = "gender";
public static final String AGE = "age";
public static final String HEIGHT = "height";
public static final String WEIGHT = "weight";
public static final String GOAL = "goal";
private static final String CREATE_TABLE_GOAL = "CREATE TABLE " + TABLE_GOAL + " (" +
GOAL_ID + " INTEGER PRIMARY KEY, " +
GENDER + " text not null, " +
AGE + " text not null, "+
HEIGHT + " text not null, "+
WEIGHT + " text not null, "+
GOAL + " text not null "+
" );";
this is SQLControlerWeight.java
public void insertGoal(String gd,String age,String hg,String wg,,String gl) {
ContentValues cv = new ContentValues();
cv.put(DBHelperNote.GENDER, gd);
cv.put(DBHelperNote.AGE, age);
cv.put(DBHelperNote.HEIGHT, hg);
cv.put(DBHelperNote.WEIGHT, wg);
cv.put(DBHelperNote.GOAL, gl);
database.insert(DBHelperNote.TABLE_GOAL, null, cv);
}
public Cursor readGoal() {
String[] allColummn = new String[] {
DBHelperNote.GOAL_ID,
DBHelperNote.GENDER,
DBHelperNote.AGE,
DBHelperNote.HEIGHT,
DBHelperNote.WEIGHT,
DBHelperNote.GOAL,
};
Cursor c = database.query(DBHelperNote.TABLE_GOAL, allColummn, null,
null, null, null, null);
if (c != null) {
c.moveToFirst();
}
return c;
}
this actually is the method to read data put but it is from array mean multiple row , but i don't Know how to change it to only call one row
dbconnection = new SQLControlerWeight(this);
dbconnection.openDatabase();
Cursor cursor = dbconnection.readGoal();
String[] from = new String[]{
DBHelperNote.GOAL_ID,
DBHelperNote.GENDER,
DBHelperNote.AGE,
DBHelperNote.HEIGHT,
DBHelperNote.WEIGHT,
DBHelperNote.GOAL,
};
int[] to = new int[]{
R.id.goal_id,
R.id.field_gender,
R.id.field_age,
R.id.field_height,
R.id.field_weight,
R.id.field_goal,
};
As you will be having GOAL_ID ones inserted you can modify you insert function as
public void insertGoal(String goal_id, String gd,String age,String hg,String wg,,String gl) {
ContentValues cv = new ContentValues();
if (goal_id != null){
cv.put(DBHelperNote.GOAL_ID, goal_id);
}
cv.put(DBHelperNote.GENDER, gd);
cv.put(DBHelperNote.AGE, age);
cv.put(DBHelperNote.HEIGHT, hg);
cv.put(DBHelperNote.WEIGHT, wg);
cv.put(DBHelperNote.GOAL, gl);
database.replace(DBHelperNote.TABLE_GOAL, null, cv);
}
Modification done is changed insert to replace, which will make sure if primary key value is provided and row exists with that id then it will replace the existing row without creating new one. Most important is the if condition for checking whether goal_id is null or not, if null then don't provide that in contentvalue.
Modify the if condition properly for proper comparison for Goal_id as i have just used the one i can visualize from your question content.
Use RawQuery method its little bit easier.
c1 = db.rawQuery("select * from Table_Name", null);
c1.moveToFirst();
do {
str = c1.getString(c1.getColumnIndex("FieldName"));
ab.add(str);
} while (c1.moveToNext());
I'm a beginner and don't know how to insert and get the current date by using database.
For an insert into the database, I use a button for adding the information. Here is the full code:
public void Badd_Click(View view) {
db.execSQL("INSERT INTO Demo (event, venue, amount, textView) VALUES ('" + tEvent.getText().toString() + "'," + "'" + tLocation.getText().toString() + "'," + "'" + tAmount.getText().toString() +"' )");
Toast.makeText(this, "Create record successfully...", Toast.LENGTH_SHORT).show();
}
Then, for showing the information inserted into the database, I also use a button:
public void Btnshow_Click(View view){
String str = "";
Cursor c = db.rawQuery("SELECT * FROM "+DATABASE_TABLE,null);
c.moveToFirst();
for(int i = 0; i<c.getCount();i++){
str+="ID: "+c.getString(0)+"\n";
str+="Name : "+c.getString(1)+"\n";
str+="Location : "+c.getString(2)+"\n";
str+="Amount : "+c.getString(3)+"\n\n";
c.moveToNext();
}
I have searched for many solutions, but I am unable to do it successfully.
Please help :(
You can use below two methods to save and retrieve date from database in the format you want.
public static String getDbDateString(Date date) {
SimpleDateFormat sdf = new SimpleDateFormat(DATE_FORMAT);
return sdf.format(date);
}
public static Date getDateFromDb(String dateText) {
SimpleDateFormat dbDateFormat = new SimpleDateFormat("yyyyMMdd");
try {
return dbDateFormat.parse(dateText);
} catch ( ParseException e ) {
e.printStackTrace();
return null;
}
}
You can get current date with below code:
Date date = new Date(System.currentTimeMillis());
To add to database:
public void addDate() {
SQLiteDatabase db = this.getWritableDatabase();
ContentValues values = new ContentValues();
values.put("key", "value");
// Inserting Row
db.insert(table_name, null, values);
db.close(); // Closing database connection
}
To read from database:
public Date getDate(int id) {
SQLiteDatabase db = this.getReadableDatabase();
Cursor cursor = db.query(table_name,
new String[]{column_id,
column_date_value},
column_id + "=?",
new String[]{String.valueOf(id)}, null, null, null, null);
if (cursor != null)
cursor.moveToFirst();
assert cursor != null;
return new Date(cursor.getString(index_column_date));
}
Actually I am working on this for the last 3 or 4 weeks but have not able to resolve it.
I am working on Sqlite Database in android in which I have used a date picker control in my activity Once a user sets a date then i'll stored the date into the string and then sends it to the database it is working fine but when i tried to retrieve the date on the basis of date set on date picker control then it doesn't give me the desired output it show the only a line which is opening a database on my catlog.
Database Class
//Table Definition with Columns
private static final String CREATE_MYCOMPANY =
"create table company " + " (" + "_id" + " integer primary key autoincrement, "
+ "company_date" +" date);";
//Insert Method
public long create(String str) {
ContentValues args = new ContentValues();
args.put(KEY_COMPANY_DATE, str);
return mDb.insert(MYCOMPANY, null,args);
}
//Method For Fetching the row on the basis of Date.//
public Cursor fetchdate(String datr) throws SQLException, ParseException {
Cursor mCursor =
mDb.query(true, MYCOMPANY, new String[] {KEY_COMPANY_ID,
KEY_COMPANY_DATE}, KEY_COMPANY_DATE /*+" BETWEEN date('2012-6-10') AND date('2012-6-14')"*/
+ " = " + datr, null,
null, null, null, null);
if (mCursor != null) {
mCursor.moveToFirst();
}
return mCursor;
}
Activity Class Code
//Date picker
DatePicker dt = (DatePicker)findViewById(R.id.datePicker1);
//Converting the Date into the string format
String day = String.valueOf(dt.getYear())+"-" +String.valueOf(dt.getMonth() + 1)
+"-"+String.valueOf(dt.getDayOfMonth());
//Method for displaying the rows of table on date basis
public void DisplayAllCmpData(){
employeeTable.open();
try{
Cursor c = employeeTable.fetchdate("2012-6-13");
if (c.moveToFirst())
{
do {
System.out.println("bool2");
DisplayCmpTitle(c);
} while (c.moveToNext());
}
}catch(Exception e){
System.out.println(e);
Toast.makeText(this,e.toString(),Toast.LENGTH_LONG).show();
}
employeeTable.close();
}
//Function For Displaying the all record.//
public void DisplayCmpTitle(Cursor c)
{
System.out.println("bool");
Toast.makeText(this,
"ID: " + c.getString(0) + "\n" +
"DATE: " + c.getString(1)
, Toast.LENGTH_LONG).show();
}
Thanks for any help in advance!!!!!!
mDb.query(true, MYCOMPANY, new String[] {KEY_COMPANY_ID,
KEY_COMPANY_DATE}, KEY_COMPANY_DATE /*+" BETWEEN date('2012-6-10') AND date('2012-6-14')"*/
+ " = '" + datr+"'", null,
null, null, null, null);
I have stored the date as string in sqlite database table. What i need i i have to retrieve the values which stored in last seven days. I have tried by using following but it doesn't showing any values.
My Database function
public Cursor paymentWeek(Activity activity)
{
String[] from = { _PAYMENTID, NAME, REQUESTEDDATE, FROMAD, TOADD, EMAILBODYPAYMENT, AMOUNT};
SQLiteDatabase db = getReadableDatabase();
String orderby = REQUESTEDDATE+" DESC";
Cursor cursor = db.rawQuery("select * from " + PAYMENTTABLE + " where " + REQUESTEDDATE + " BETWEEN "
+ "date('now')" + " AND " + "date('now','-7 days')", null);
activity.startManagingCursor(cursor);
return cursor;
}
Calling function
Cursor week = db.paymentWeek(this);
String[] weekly = new String[] { PaymentAppDataBase.REQUESTEDDATE,PaymentAppDataBase.PAYMENTNAME,PaymentAppDataBase.AMOUNT };
int[] sevendays = new int[] { R.id.Date,R.id.Name,R.id.Amount };
SimpleCursorAdapter weekcursor =
new SimpleCursorAdapter(this, R.layout.listview, week, weekly, sevendays);
setListAdapter(weekcursor);
db.close();
It would be helpful if you guys sort out this problem. I get stuck over here.
try Following query to get records for last week(7 days):
"select * from " + PAYMENTTABLE + " where " + REQUESTEDDATE + "DATE_SUB( CURDATE( ) ,INTERVAL 7 DAY ) AND CURDATE( )";
You don't have to change your db design.
Just write your own convert from dateString to long method, and put it in class like DateUtil.java, then call it wherever you want to do something with date type.
The method should look like this:
public static long convertStringDateToLong(String date, String yourDateFormat) {
Long time = 0L;
try {
SimpleDateFormat df = new SimpleDateFormat(yourDateFormat);
Date d = null;
try {
d = df.parse(date);
} catch (ParseException e) {
e.printStackTrace();
}
time = d.getTime();
} catch (Exception e) {
e.printStackTrace();
}
return time;
}
where yourDateFormat should be something like: "MM/dd/yyyy"