I am making an android app (my first) to record gym workouts but I am not sure on how to best structure the database for storing this data.
I want to be able to store:
A list of exercises and their properties
A list of workouts and their properties (containing exercises)
A list of logged workouts (workout and date of workout)
All the set data from each logged workout (exercise, number of sets, weight of each set, reps of each set)
I have drawn up the following schema for how I thought this could be implemented:
My main questions are:
Is it optimal to store all the individual set log data in a single table (Log Entries)?
Should the Exercise Type and Equipment tables be separate or just columns in the Exercise Table? Same goes for Workout Type
Would this be a good approach in terms of performance/usability?
Thanks!
Is it optimal to store all the individual set log data in a single
table (Log Entries)?
In all likeliehood yes, the exception would be if the number of rows grew to adversely impact response times.
Should the Exercise Type and Equipment tables be separate or just
columns in the Exercise Table? Same goes for Workout Type
They should be separate to reduce unnecessary duplication and issue e.g. if you were to change a type or and equipment then you'd have to apply that change to all rows in the exercise table with a separate table you just have to make the one change.
Would this be a good approach in terms of performance/usability?
With the exception of the Log table (as it stands including wanting the date) then it appears to be a good and efficient approach. The Log table isn't needed as the Log Entries table has a column for the date time (So in response to the comment yes it would be better to make use of the date/time in the Log Entries and to do away with the log table).
Related
I'd like to optimize an app, kinda scheduler. I have tasks with different statuses like done, to do and archived(after delete). App logic uses the first two types the most, so should I keep them in the same table(and just selecting done & to do every time I need) or should I do a copy table just for archived items to make the select "easier" because status archived is very rarely used.
So does sqLite db size affects somehow db operations or not? I tested select operations in big tables(only one in whole db) and it take a long time to process 100K - 1M rows
SQLite has no problem with big tables and 1 millions records is not really big.
You should use only multiple tables if it makes sense logically, performance is not an issue. So your only table could look like this:
tasks table
---------------------------
id (primary key)
title (indexed)
description
status (or status_id) (indexed)
A rule of thumb is to index all columns you use in the where clauses of your queries.
If you use strings as status in your DB then you could use another table and refer to it in your tasks table with a foreign key to the id of this table:
status table
------------
id
name
I'm fairly new to sqlite and from my understanding you can't store individual tables per row of a current table. Due to that, would it than be acceptable to have a table that has greater than 50+ columns or would it be best to split the columns into more tables?
To get where I'm coming here's a simplified concept of what I'm trying to create:
A table called History stores the data, user weight, and a foreign id referencing the exercise table.
In the exercise table there are columns
Workout-1-Name, Workout-1-Weight, Workout_1_MAX_SET,Workout_1_SET_1.,.,..,..Workout_1_SET_8
and this repeats for Workout_2 - Workout_5. As you can see it will be pretty long(Around 50 columns).
I was thinking of just creating separate tables for Workouts 1-5 but since they're all workouts wouldn't it make sense to just store them all in one table?
Also, is there a cleaner way to do this? Writing all of this out in java seems messy even with static names.
Thanks, appreciate any responses.
For my Android app, I want to save data using sqlite with this format:
name, date, attr1, attr2, attr3,...
These are the requirements:
each date can only contain each name once
there can be a variable number of attributes(numbers) for each name
each specific name has the same number of attributes
The app will be used to track events throughout the day. Events can have zero or more numeric properties.
The questions are: is sqlite the best way to store things here? If so how do I design my database? What other ways are there to store this kind of data?
is sqlite the best way to store things here?
This will depend on a number of other factors, such as how the data will be queried and used, the volume of transactions, data growth and retention, etc. From what you've described, though, SQLite is a great option, offering functionality out-of-the-box that supports some of your requirements directly, and is commonly used in such cases.
If you don't have much experience with relational databases, implementing this functionality may seem difficult at first, but like learning a new language or framework, it will get easier with time.
If so how do I design my database?
Let's step through each of your enumerated requirements...
each date can only contain each name once
SQLite supports the UNIQUE constraint. For example, if your columns were named name and date, you could add the following to your CREATE TABLE statement:
UNIQUE(name, date)
(A more complete CREATE TABLE statement is in the next example below, and it includes this constraint.)
This constraint prevents the insertion of rows with name/date pairs that already exist. Using android.database.sqlite.SQLiteDatabase, if you attempt to insert a row into the table with a duplicate name/date pair, a SQLiteConstraintException will be thrown at runtime. You will need to handle this exception in your java code.
there can be a variable number of attributes(numbers) for each name
This is a textbook case for normalizing the database, putting your data into multiple tables. For example:
CREATE TABLE names (
name_id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
name TEXT NOT NULL,
date DATETIME,
UNIQUE(name, date));
CREATE TABLE attrs (
name_id INTEGER NOT NULL,
attr_value INTEGER NOT NULL,
FOREIGN KEY(attr_value) REFERENCES names(name_id));
Your queries that retrieve attribute data would then JOIN the two tables. Since you indicated that "Events can have zero or more numeric properties", a LEFT OUTER JOIN might be most appropriate, as it will return names and dates even if there are no attributes.
Here's an example query, by name:
SELECT n.name, n.date, a.attr_value
FROM names AS n
LEFT OUTER JOIN attrs AS a
ON n.name_id = a.name_id
WHERE n.name = 'SMITH'
ORDER BY n.name, n.date, a.attr_value;
This query would return results like the following:
name date attr_value
--------------- ---------- ------------
SMITH 2015-02-13 1027
SMITH 2015-02-13 4426
SMITH 2015-02-13 8390
SMITH 2015-02-20 4426
SMITH 2015-02-20 8152
SMITH 2015-02-20 9328
You can then iterate through and process these results in java. If your results include multiple names and/or dates, then in your loop you should keep track of the last used name and date. If the name/date in the current record is the same, the attribute belongs to the current one. If the name/date is different, then this is a new one.
Note that this approach to your database design is flexible, allowing you to query on the attributes, for instance, to see what name/date pairs are associated.
Also note that there is a FOREIGN KEY constraint on the attrs table, meaning that if you attempt to insert a record into that table with a name_id that does not exist in the names table, a SQLiteConstraintException will be thrown at runtime. You will need to handle this exception in your java code.
each specific name has the same number of attributes
You will need to accommodate this requirement in your java code, probably doing some checks in the database prior to performing an INSERT.
What other ways are there to store this kind of data?
Flat files, JSON, XML, third-party data stores (with their own libraries), to name a few.
I'm not sure but I think the best way to achieve your requirement is to use sqlite and to solve your problem you can have 3 columns only. One for the name and one for the date and the other contains a JSON array that represents the rest of the attributes.
In my Android app, I need to temporarily store some data in a form of table such as follows:
id | column 1 | column 2 | ... | column n
The data are downloaded from a server whenever users press a button. However, the data table doesn't have a fix number of column (as well as row) every time user downloads it from the server. For example, the server may send data with 3 columns the first time. Then it might send data with 5 columns the second time, etc...
Given this scenario, I think the database is probably the right data structure to use. My plan is to create a database, then add and delete tables as necessary. So I have been reading various tutorials on Android database (one example is this one http://www.codeproject.com/Articles/119293/Using-SQLite-Database-with-Android#). It seems to me I cannot create new table with variable number of columns using the sqlite database. Is this correct? In the onCreate(SQLiteDatabase db) method, the "create table" command must be specified with known number of columns and their data types. I could provide several "create table" commands, each with different number of columns but that seems like very crude. Is there a way to create database tables with variable number of columns on the fly?
Another alternative probably using several hash tables, each storing one column of the data table. I'm seriously considering this approach if the database approach is not possible. Any better suggestion is welcomed.
There is no such thing as a variable number of columns in an SQLite data base. Also, adding and deleting tables dynamically seems like a horrible hack.
It sounds like you want to store an array of values associated with an id. I suggest you think in terms of rows, not columns. Use a table structure like (id, index, value); each array of values returned by the server results in as many rows as necessary to store the values.
this is more of a question of theory than anything else. I am writing an android app that uses a pre-packaged database. The purpose of the app is solely to search through this database and return values. Ill provide some abstract examples to illustrate my implementation and quandary. The user can search by: "Thing Name," and what I want returned to the user is values a, b, and c. I initially designed the database to have it all contained on a single sheet, and have column 1 be key_index, column 2 be name, column 3 be a, etc etc. When the user searches, the cursor will return the key_index, and then use that to pull values a b and c.
However, in my database "Thing alpha" can have a value a = 4 or a = 6. I do not want to repeat data in the database, i.e. have multiple rows with the same thing alpha, only separate "a" values. So what is the best way to organize the data given this situation? Do I keep all the "Thing Names" in a single sheet, and all the data separately. This is really a question of proper database design, which is definitely something foreign to me. Thanks for your help!
There's a thing called database normalization http://en.wikipedia.org/wiki/Database_normalization. You usually want to avoid redundancy and dependency in the DB entities using a corresponding design with surrogate keys and foreign keys and so on. Your "thing aplpha" looks like you want to have a many-to-many table like e.g. one or many songs belong/s to the same or different genres. You may want to create dictionary tables to hold your id,name pairs and have foreign keys referencing these tables. In your case it will be mostly a read-only DB so you might want to consider creating indexes with high FILLFACTOR percentage don't think sqlite allows it to do though. There're many ways to design the database. Everything depends on the purpose of DB. You can start with a design of your hardware like raids/file systems/db block sizes to match the F-System's block sizes in order to keep the I/O optimal and where to put your tablespaces/filegroups/indexes to balance the i/o load. The whole DB design theory/task is really a deep subject which is not to be underestimated nor is a matter of few sentences in the answer of stackoverflow. :)
without understanding your data better here is my guess at what you are looking for.
table: product
- _id
- name
table: attribute
- product_id
- a