I want to design a database where I have customers who daily buy varying quantities of any dairy product(milk, curd, cheese) but pay at the end of the month.
I am unable to figure out the correct database schema as I want to store each day's quantity of a particular product and a customer can buy multiple types of products.
So, what should be the way forward?
EDIT: My schema
Customer:
-Customer ID
-Name
-Mobile Number unique
-Address
-Daily Quantity(just for reference. during transaction it can increase or
decrease as per requirement)
Product:
-Product Id
-Name
-Price per unit
Transaction Table
-Customer id (foreign key)
-product id (foreign key)
-Quantity
-Date
Now, i want to generate a monthly bill for each customer by combining all the different items he bought over the month. So, will this transaction table be the best approach to do so?
I´ve add a new table Ticket so every single product bought during the day belongs to a unique Ticket.
This way you can get back to a specific ticket and see how much was spend ( this is because prices could change and there are multiple tickets during one day ).
<Ticket>
-Product id (foreign key)
-Quantity
-total
-Date
I´ve modified your Transaction table to have only ticket-customer relationship.
<Transaction>
-customer_id (foreign key)
-ticket id (foreign key)
-Date
Some SQL example
SELECT Tr.customer_id, MONTH(tr.Date), SUM(ti.total)
FROM Transaction tr, Ticket ti
WHERE tr.ticket_id = ti.id
GROUP BY MONTH(tr.Date)
WHERE Tr.customer_id = ? AND tr.Date BETWEEN ? AND ?
I'm designing what is essentially an accounting/retailing application for MS SQL Server 2016. I have ~75 core data object types, each in their own respective table (users, organizations, invoices, payments, etc.).
What I need to create is a notification system,
e.g. "Steve paid invoice 1234", "Bob purchased product XYZ", etc. What I was going to create was a "notification types" table:
NotificationTypes:
id message
11 "{0} paid invoice {1]"
12 "{0} purchased product {1]"
...
and then have two corresponding tables that store each notification event's info, and then the values for that notification message. So for example for "Steve paid invoice 1234":
NotificationEvent:
id notificationType (FK) occured
21 11 2016-01-01 00:00:00
NotificationEventValues:
id notificationEvent (FK) XXXXX
31 21 (FK reference to Steve in users table)
32 21 (FK reference to invoice 1234 in invoices table)
Now since I can't create generic foreign keys for NotificationEventValues.XXXXX, I was going to have a single 'dataObjects' table that has FK columns for all 75 data types I have, with only one of the 'data type' columns having a value per row.
This way, every instance of a data object in my database has a unique ID I can reference in the notification field - which will mean a huge table given it has a unique ID for basically every row in the other 75 tables. The other downside is it means for every user, invoice, any 'data object', I'm wasting significant amounts of space since space will be reserved for ID references for the other 74 null-valued columns (since they're fixed size IDs and not variable).
ASK:
Is there a better way to achieve my 'global' identifier across all the tables? Or a better way to handle the notification system to avoid this problem?
Create triggers in all table that will insert a record in a table say KeyMaster with one column key which will also be the primry key whenever a record is inserted in any table. The value inserted in this table will be in the format _. For example if a record is inserted in user table with id 1 then the record inserted in KeyMaster table will be 'user_1'. Similarly if a record is inserted in invoice table with id 1 then the recor inserted in KeyMaster table will be 'invoice_1'.
In your NotificationEventValues table you will need only three columns id,notificationEvent and key (FK reference to KeyMaster table).
For getting corresponding record you need to write query similar to below:
select *
from NotificationEventValues n
inner join users u on 'user_' + u.id = n.key
If I had a single record that represented, say, a sellable item:
ItemID | Name
-------------
101 | Chips
102 | Candy bar
103 | Beer
I need to create a relationship between these items and one or more different types of PKs. For instance, a company might have an inventory that included chips; a store might have an inventory that includes chips and a candy bar, and the night shift might carry chips, candy bars, and beer. The is that we have different kinds of IDs: CompanyID, StoreID, ShiftID respectively.
My first though was "Oh just create link tables that link Company to inventory items, Stores to inventory items, and shifts to inventory items" and that way if I needed to look up the inventory collection for any of those entities, I could query them explicitly. However, the UI shows that I should be able to compile a list arbitrarily (e.g. show me all inventory items for company a, all west valley stores and Team BrewHa who is at an east valley store) and then display them grouped by their respective entity:
Company A
---------
- Chips
West Valley 1
-------------
- Chips
- Candy Bar
West Valley 2
-------------
- Chips
BrewHa (East Valley 6)
--------------------
- Chips
- Candy Bar
- Beer
So again, my first though was to base the query on the provided information (what kinds of IDs did they give me) and then just union them together with some extra info for grouping (candidate keys like IDType+ID) so that the result looked kind of like this:
IDType | ID | InventoryItemID
------------------------------
1 |100 | 1
2 |200 | 1
2 |200 | 2
2 |201 | 1
3 |300 | 1
3 |300 | 2
3 |300 | 3
I guess this would work, but it seems incredibly inefficient and contrived to me; I'm not even sure how the parameters of that sproc would work... So my question to everyone is: is this even the right approach? Can anyone explain alternative or better approaches to solve the problem of creating and managing these relationships?
It's hard to ascertain what you want as I don't know the purpose/use of this data. I'm not well-versed in normalization, but perhaps a star schema might work for you. Please keep in mind, I'm using my best guess for the terminology. What I was thinking would look like this:
tbl_Current_Inventory(Fact Table) records current Inventory
InventoryID INT NOT NULL FOREIGN KEY REFERENCES tbl_Inventory(ID),
CompanyID INT NULL FOREIGN KEY REFERENCES tbl_Company(ID),
StoreID INT NULL FOREIGN KEY REFERENCES tbl_Store(ID),
ShiftID INT NULL FOREIGN KEY REFERENCES tbl_Shift(ID),
Shipped_Date DATE --not really sure, just an example,
CONSTRAINT clustered_unique CLUSTERED(InventoryID,CompanyID,StoreID,ShiftID)
tbl_Inventory(Fact Table 2)
ID NOT NULL INT,
ProductID INT NOT NULL FOREIGN KEY REFERENCES tbl_Product(ID),
PRIMARY KEY(ID,ProductID)
tbl_Store(Fact Table 3)
ID INT PRIMARY KEY,
CompanyID INT FOREIGN KEY REFERENCES tbl_Company(ID),
RegionID INT FOREIGN KEY REFERENCES tbl_Region(ID)
tbl_Product(Dimension Table)
ID INT PRIMARY KEY,
Product_Name VARCHAR(25)
tbl_Company(Dimension Table)
ID INT PRIMARY KEY,
Company_Name VARCHAR(25)
tbl_Region(Dimension Table)
ID PRIMARY KEY,
Region_Name VARCHAR(25)
tbl_Shift(Dimension Table)
ID INT PRIMARY KEY,
Shift_Name VARCHAR(25)
Start_Time TIME,
End_Time TIME
So a little explanation. Each dimension table holds only distinct values like tbl_Region. Lists each region's name once and an ID.
Now for tbl_Current_Inventory, that will hold all the columns. I have companyID and StoreID both in their for a reason. Because this table can hold company inventory information(NULL StoreID and NULL shiftID) AND it can hold Store Inventory information.
Then as for querying this, I would create a view that joins each table, then simply query the view. Then of course there's indexes, but I don't think you asked for that. Also notice I only had like one column per dimension table. My guess is that you'll probably have more columns then just the name of something.
Overall, this helps eliminate a lot of duplicate data. And strikes a good balance at performance and not overly complicated data structure. Really though, if you slap a view on it, and query the view, it should perform quite well especially if you add some good indexes.
This may not be a perfect solution or even the one you need, but hopefully it at least gives you some ideas or some direction.
If you need any more explanation or anything else, just let me know.
In a normalized database, you implement a many-to-many relationship by creating a table that defines the relationships between entities just as you thought initially. It might seem contrived, but it gives you the functionality you need. In your case I would create a table for the relationship called something like "Carries" with the primary key of (ProductId, StoreId, ShiftId). Sometimes you can break normalization rules for performance, but it comes with side effects.
I recommend picking up a good book on designing relational databases. Here's a starter on a few topics:
http://en.wikipedia.org/wiki/Entity%E2%80%93relationship_model
http://en.wikipedia.org/wiki/Database_normalization
You need to break it down to inventory belongs to a store and a shift
Inventory does does not belong to a company - a store belongs to a company
If the company holds inventory directly then I would create a store name warehouse
A store belongs to a region
Don't design for the UI - put the data in 3NF
Tables:
Company ID, name
Store ID, name
Region ID, name
Product ID, name
Shift ID, name
CompanyToStore CompanyID, StoreID (composite PK)
RegionToStore RegionID, StoreID (composite PK)
Inventory StoreID, ShiftID, ProductID (composite PK)
The composite PK are not just efficient they prevent duplicates
The join tables should have their own ID as PK
Let the relationships they are managing be the PK
If you want to report by company across all shifts you would have a query like this
select distinct store.Name, Product.Name
from Inventory
join Store
on Inventory.StoreID = Store.ID
join CompanyToStore
on Store.ID = CompanyToStore.StoreID
and CompanyToStore.CompanyID = X
store count in a region
select RegionName, count(*)
from RegionToStore
join Region
on Region.ID = RegionToStore.RegionID
group by RegionName
I am currently creating an Android application which should use SQLite database. In my case, I need to strore "product type", "bill" and "list of all purchased products"
Bill:
id
customer
data -> link to list of all purchased products
price
Product types:
id
name
price
My question is: One customer could have more products connected to one bill. How to design it? Is using a Use a one row for every bills:
id
bill_id
product
or rather insert more products into one row and then parse it in my application? I suppose, there is a better solution that these mine. Thank you for help.
You said in your question, "One customer could have more products connected to one bill."
Another way of saying this is, one customer can have 0 or more bills, and one bill can have 1 or more products.
After rephrasing your statement, the database normalization becomes more obvious.
Customer
--------
Customer ID
Customer Name
...
Bill
----
Bill ID
Customer ID
Bill Time Stamp
Bill-Product
------------
Bill ID
Product ID
Product
-------
Product ID
Product Name
Product Price
...
To design customer order with bill we can design it as below:
This schema having basics attributes we can add more as per requirements.
Customers Table
id PK
full_name
address
phone
MenuItems Table
id PK
item_name
item_description
item_price
Order Table
id PK
customer_id FK
order_date
OrderDetails Table
id PK
order_id FK
menu_item_id fk
quantity
Bill Table
id PK
order_id FK
amount
bill_date
I am creating a small playlist program on VB, which contains adduser, deleteuser and also user can modify its playlist.
My stupid question is, how do I manage user playlist? Consider I am using database, where should I add user?
As a new table in Database?
As a new Entry in some kind of Table which contains userID, Name and its undefined number of choices?
If I select option 2, what kind of datatype handles a integer set of undefined size?
Thank you.
You would create 3 tables:
Users table
-----------
userID
email
password
name
Playlist table
--------------
playlistID
userID
trackID
Tracks table
------------
trackID
trackName
You would then create relationship between the tables:
Users.userID 1-* Playlist.userID (1 to many)
Tracks.trackID 1-* Playlist.trackID (1 to many)
Then you would store the users choices in the playlist table.
To see a users tracks you could do:
SELECT Playlist.trackID, Tracks.trackName
FROM Playlist
JOIN Tracks ON Playlist.trackID=Tracks.trackID
WHERE Playlist.userID = 12
ORDER BY Tracks.trackName
This is the basics of relational database system and normalisation of data.
For more information see:
http://www.dreamincode.net/forums/topic/179103-relational-database-design-normalization/