Android - Configuring SQLite Tables to meet my needs - android

I am having trouble figuring out what to do with my tables.
Scenario -
Recipe Book!
I have a home page with an add button, when clicked on that I add a meal, when meal save button is clicked I add a recipe. Now Here is where it gets tricky.
On my recipe add page I want to be able to Add an ingredient then have the option (Press + button) to add another ingredient, but I am unsure on how to go about this....
Tables Currently:
Meal Table
e.g Meal id, meal name
Recipe table
e.g Recipe id, recipe name, Ingredients
Now do I have to make a table called Ingredients with 20 columns for a user to be able to put in 20 ingredients or is there a simpler way??
Any help would be great.
EDIT: Silly question

By basic Database Principles, multi valued attributes (ingredients in your case) should be placed in a different table with the (ingredient id, recipe id) as the primary key. In this table you can have 3 columns namely recipe id, ingredient id and ingredient name. I hope this is what you wanted to achieve.

You have a couple of options. You can link your ingredients to another table or you can serialize your ingredients list into a single value for storage and deserialize it on retrieval.

Related

How to model a relational database that stores order details?

I am making a restaurant POS app for android and I am trying to decide the best way to model the database for it using Room ORM that ensures maintainability. My database needs, among a lot of other things, to keep a record of all items sold within a transaction/order, as well as a log of the orders themselves and a list of the food products sold within the restaurant.
Considering the following tables (for brevity purposes I only include columns I think relevant to the question and may not illustrate all the information I will need to catalog), I can create a table that includes a log of all the orders ever placed and call it all_orders:
all_orders
-----------
id (PK)
oder_details_id (FK) - referencing the PK from order_details table
date
notes
total
payment_type
I can also create a table that contains all the food products/dishes that the restaurant serves, and we’ll call it all_items:
all_items
---------
id (PK)
name
category
price
No problems there so far, but my current confusion lies here—how do I manage to keep a log of the actual food items sold within an order?
One approach I thought about was to create a table per order number, but creating tables dynamically is already a problem and having 60,000 tables at the end of the year will be a maintainability nightmare.
So my other possible solution is to create a table called order_details that will probably end up with hundreds of thousands of entries per year with the following columns:
order_details
-------------
id (PK)
item_id (FK) - referencing the PK from the all_items table
order_id (FK) - referencing the PK from the all_orders table
quantity_ordered
And when a user wants to pull up an order from say, last week, the program can use a join query that will produce the following to be displayed in the app’s UI:
order
---------
id (PK)
date (from the all_orders table)
name (from all_items)
category (from all_items)
price (from all_items)
total (from all_orders)
payment_type (from all_orders)
I am afraid that the order_details table is just too broad since it will contain hundreds of thousands of entries, and querying it for entries will be sluggish. I'm sure indexing it will help, but is this the correct approach to this problem? If not, is there a better, “best practice” solution? If possible something that focuses on grouping any order and its items together without just dumping all items from all orders into one table. Any help will be most appreciated.
Edit: This question is not a duplicate of this, and while helpful, the supplied link has not provided any additional context on what I am really asking about nor is it entirely relevant to the answer I am after. I have bolded my last original paragraph since my question is really about a how I can model the above data as it isn't clear to me based on my research how to store actual order details attached to an order (many tutorials/similar questions I've come across fail short of thoroughly explaining the aforementioned).
The all_orders table would be superfluous as that is just repeating other data and would be contrary to normalisation.
You probably want a category table rather than repeat data (i.e. normalise categories).
Likewise, you also probably want a payment_type table (again to normalise).
Creating individual tables for orders would probably just create a nightmare.
Price and total aren't they the same? Saying that totals can be derived when extracting the data so there is no need to store such information.
As such the following structure schema may be close to what you want :-
DROP TABLE IF EXISTS item;
DROP TABLE IF EXISTS category;
CREATE TABLE IF NOT EXISTS category (_id INTEGER PRIMARY KEY, category_name TEXT);
CREATE TABLE IF NOT EXISTS item (
_id INTEGER PRIMARY KEY,
item_name TEXT UNIQUE,
category_ref INTEGER REFERENCES category(_id) ON DELETE CASCADE ON UPDATE CASCADE,
item_price REAL
);
DROP TABLE IF EXISTS payment_type;
CREATE TABLE IF NOT EXISTS payment_type (
_id INTEGER PRIMARY KEY,
payment_type TEXT UNIQUE,
surcharge REAL
);
-- NOTE cannot call a table order as it is a keyword (not rea true but have to enclose the name e.g.g [order]).
DROP TABLE IF EXISTS customer_order;
CREATE TABLE IF NOT EXISTS customer_order (
_id INTEGER PRIMARY KEY,
customer_name TEXT,
date TEXT DEFAULT CURRENT_TIMESTAMP,
payment_type_ref INTEGER REFERENCES payment_type(_id) ON DELETE CASCADE ON UPDATE CASCADE
);
DROP TABLE IF EXISTS order_detail;
CREATE TABLE IF NOT EXISTS order_detail (
customer_order_ref INTEGER REFERENCES customer_order(_id) ON DELETE CASCADE ON UPDATE CASCADE,
item_ref REFERENCES item(_id) ON DELETE CASCADE ON UPDATE CASCADE,
quantity
);
Example
The following is native SQL that demonstrates the schema above :-
Part 1 adding (inserting) the data :-
INSERT INTO category (category_name) VALUES
('Fish'),('Beef'),('Chicken'),('Lamb'),('Sea Food')
;
INSERT INTO item (item_name, item_price, category_ref) VALUES
('Fish and Chips',11.30,1),
('Steak and Kidney Pudding',15.45,2),
('Lamb Chops, Mashed Potato and Gravy',17.40,3)
;
INSERT INTO payment_type (payment_type, surcharge) VALUES
('Master Card',0.05),('Visa',0.05),('Cash',0),('American Express',0.15)
;
INSERT INTO customer_order (customer_name, payment_type_ref) VALUES
('Fred',3),
('Mary',1),
('Tom',2),
('Jane',4)
;
INSERT INTO order_detail (customer_order_ref, item_ref, quantity) VALUES
(1,1,2),(1,2,1), -- Fred (id 1) orders 2 Fish and Chips (id 1) and 1 Steak and Kidney (id 2)
(2,3,10), -- Mary orders 10 Lamb chops
(3,2,1),(3,1,1),(3,3,1), -- Tom orders 1 of each
(4,1,1) -- Just Fish and chips for Jane
;
Part 2 - Extracting Useful(perhaps) Data
Here's and example of what you can do with SQL which includes derived data (as suggested above) :-
SELECT
customer_name,
date,
group_concat(item_name) ||'('||quantity||')' AS items,
sum(item_price) AS total_price,
payment_type,
round(sum(item_price) * surcharge,2) AS surcharge,
round((sum(item_price) * surcharge) + sum(item_price),2) AS total_price
FROM customer_order
JOIN order_detail ON customer_order._id = order_detail.customer_order_ref
JOIN item ON order_detail.item_ref = item._id
JOIN payment_type ON customer_order.payment_type_ref = payment_type._id
GROUP BY customer_order._id -- Treats all data for an order as a single row allowing the use of aggregate functions on the groups e.g. sum, group_concat
;
Result

Storing/retrieving highly dynamic data from an Android app

I'm trying to develop an Android app to help me test ceramic glazes, and have run into a problem with storing data. The main feature I want is, within one glaze, the ability to modify its recipe, yet still keep the older versions of that recipe. Since a lot of my data is repetitive (finish, opacity, firing atmosphere, etc.), a database would be the best way to store that data. However, each glaze can have any number of versions, and the recipe within each version can have any number of ingredients (normally 1-10, but as much as 20). I cannot think of a way to store and retrieve this "two dimensional" dynamic data. I could make an individual database for each glaze, but I feel that defeats the purpose of a database. Any help implementing a way to store this highly dynamic data would be appreciated. Thank you.
I think you are looking to have a number of related tables.
I'd suggest a glaze base table, containing the base glazes, a table for recipe/versioned glazes. An ingredients/properties table. An then an extended link/associative table table this being used to link ingredients properties to recipes and also contain amounts.
The Glaze Table would be very simple just the name of the glaze and a unique identifier. e.g
CREATE TABLE IF NOT EXISTS glazes (_id INTEGER PRIMARY KEY, glazename TEXT)
The GlazeVersion Table is again relatively simple, a unique identifier, the version and a reference to it's parent/base glaze. e.g.
CREATE TABLE glazeversions (_id INTEGER PRIMARY KEY, version TEXT, glazebase_ref INTEGER)
The Indgredients table is yet again simple, a unique id and name e.g.
CREATE TABLE ingredients (_id INTEGER PRIMARY KEY, ingredient TEXT)
The Recipes table would have a reference to the glazeversion (and therefore implicitly the glaze), a reference to the ingredient and a field for the amount of the ingredient e.g.
CREATE TABLE IF NOT EXISTS recipes (glazeversion_ref INTEGER, ingredient_ref INTEGER, amount INTEGER, PRIMARY KEY(glazeversion_ref, ingredient_ref))
So lets assume we have 3 base glazes RED, GREEN and BLUE. There would be 3 entries in the glazes table (with for illustrative purposes id's 1 2 and 3).
Also lets assume that each has three versions named Version001, Version002 and Version003 (9 rows in the glazeversion table id's 1-9 for illustrative purposes).
The resultant glazeversions table could be :-
A query could be written to show the links/associations/references e.g.
SELECT * FROM glazeversions JOIN glazes WHERE glazebase_ref = glazes._id ORDER BY glazename
the result would be :-
For the Ingredients table lets assume that there are 5 ingredients, Ochre, Calcium, Atmosphere, Temperature (temp for short) and Duration (id's 1-5 respectively). e.g.
Now it's onto the Recipes table, let's initially assume 1 recipe for glaze Blue version Version001 and it has 3 ingredients Atmosphere, Temp and Ochre
The recipes table would have 3 rows all three referencing the glazeversion Version001 for glaze Blue (_id 2) but each referencing the respective ingredient (id's 1, 3 and 4).
We'll also assume two other glazes:-
Red Version001 with 4 ingredients Duration, Temp, Atmosphere and Ochre so 4 rows all referencing glazeversion Version001 for Red (_id 1), respective ingredients id's 1, 3, 4 and 5.
Green Version003 with 2 ingredients Ochre and Calcium. So both rows reference glazeversion Version003 for Blue (_id 9), repective ingredients are id's 1 and 2.
So the table looks like:-
The following query is an example of tying everything together:-
SELECT glazename, version, ingredient, amount FROM recipes JOIN ingredients ON ingredient_ref = ingredients._id JOIN glazeversions ON glazeversion_ref = glazeversions._id JOIN glazes ON glazebase_ref = glazes._id
This would result in :-
If you wanted just glaze Green Version003 then you could add a WHERE clause along the lines of:-
SELECT glazename, version, ingredient, amount FROM recipes JOIN ingredients ON ingredient_ref = ingredients._id JOIN glazeversions ON glazeversion_ref = glazeversions._id JOIN glazes ON glazebase_ref = glazes._id WHERE glazeversions._id = 9
which would result in :-
You should be able to add multiple glazes that have the same identifier (say name for example), and for each one add the relevant information as well as a date. Then when you choose to view a glaze, you pull down all the info for a glaze with that identifier, and sort by the date.
Really the only extra thing you would be adding is another date, id, and name. Otherwise the entry holds all the same data you would otherwise need.

Android Sqlite Database Formation

In my application I take entry from user as :-
Name:- -------------------------
Favorite Fruit:- a)
b)
c)
--------- Add More ----------
Then I want to save it into a Sqlite database. Now I provide user to type in edittext search like this:-
Search Fruit:- Apple,Banana
And then I want to query my database and Print the name of those who like atleast Apple and Banana.
Now my issue is how do I make my database columns to achieve results faster.
Should I make two columns Name and FruitsLiked or something else. Because if I make only two colums then how do I search into database.
Thanks
Create one table n two columns. First column is for name , second one comma separated list of fruits.
Then as db query use like keyword based query

Dynamically creating tables in SQLite with user input in Android

I'm quite new to Android and the SQLite. I'm currently working on an app which requires user to create list of their favourite artists.
I have implemented some charts which already display this artist data. I believe I can easily figure out how to implement adding data to lists.
I was thinking of having two separate tables in SQLite :
Lists (which would store the list names which the user has created)
ChartItems (which would store the chart items and the lists they belong to)
However the Lists table only needs one field in this case "ListName" so I thought it might not be crucial to have a table for this.
Is it possible to dynamically create tables when getting input from a user?
For example : A user creates a list and that value is subsequently used to create a table.
Thanks.
You don't want to be creating new tables on the fly. Your proposal for two tables is fine. The list table should have at least two fields - an integer field called id or _id which is the primary key, and a text field for the list name. The Chartitems table will have a field (listid) which holds the id of the list to which it belongs. This means a chartitem can belong to only one list, and adding a chartitem to a list is achieved by setting the listid field in its record. This is a one-to-many relationship.
If you want to have a single chartitem in more than one list, then you need a many-to-many relationship, which is implemented by having a third table (links). This table will have one field mapping to a list (listid), and one field mapping to a chartitem (itemid.) To add a chartitem to a list, you create the appropriate link entry in the links table. In this case the chartitem table does not need the listid field.
I suggest reading up some more on relationships in databases to clarify these concepts. One principle I strongly suggest following is to have every table contain a field called id which is the primary key for that table, and use that for all references from other tables. In the long run this works much better than using other fields (like name) in relationships.

Beginning android: how to map a string to a list

I just finished the NotepadV1-3 tutorial for Android apps, and I was thinking of creating my own inventory app for fun, which for now basically consists of a list of names (such as "DVD" or "Grocery"), each of which can be clicked, which will bring up another specific list associated with that name. However, with the SQLiteDatabase.insert(..) method, the ContentValue can only take (among many others) "String, String" as argument, and I can't figure out how to input into the database a list of Strings associated with a particular key. I'm having trouble researching on how to resolve this as I am not that familiar with SQL.
What would be the best way to store a key with its associated list of Strings?
Any pointers and suggestions are appreciated!
Android newb :[
The best thing you could is to make a database-design that doesn't need you to input the list as as "string of strings". You might (I have not thought this trough all the way) have a table with lists (id and listName) and another table with contents (id and contentName) and finally a table that connects the two (tableId and contentName).
If you REALLY want to store that string-of-strings, you could serialize it into one string, and then when you've read it from the db, you can rebuild the string. This is NOT recommended though.
Example for a (simpler) database
Table 1 "lists": listId, listName
Table 2 "items": itemId, itemName, listId
e.g.:
Lists:
listId listName
1 DVD's
2 Grocery
Items
itemId itemName listId
1 film1 1
2 film2 1
3 sugar 2
4 milk 2
You can find all items of the grocery list by:
SELECT i.itemName
FROM lists l
JOIN items i ON l.listId = i.listId
WHERE l.listName='Grocery'

Categories

Resources