I'm a beginner in SQL and Database management, I have an idea that I don't know how to model into database tables.
I have these tables : users, orders, bills, lessons, tickets, coaches.
Lessons are posted by coaches.
The users are able to order lessons.
A bill is registered after the order.
The users are also able to order tickets.
A ticket gives access to a lesson.
When users buy a ticket, the coache benefit or half or the ticket price.
So when a user buy a ticket that costs 6$ for a specific lesson, the coache who owns the lesson will get 3$.
Do I need another bills table for the coaches? or I can use the same bills table to register their gains from the purchased lessons?
I really have no idea how to achive my List of ideas above, sorry.
For now I've just managed to do this, I don't know how to complete the rest of the DB.
|bills|<--|orders| *<------ |users|
|
v
*
|order_lesson|
*
/\
|
|lessons| *<----- |coaches|
I can't ask you for a complete answer, but I really need some explication or guidance.
From what I can tell the ticket is no different then a regular order and can be placed with the orders as the only difference is the money the coach gets. So maybe just a column in the orders table would signify the type of order.
|bills|<--|orders|<----|users|
/ \
|
|lessons|<---|coaches|
Related
Hello Stack Overflowers,
I'm redesigning a system for an ordering group.
We have a hundred or so companies (ordering accounts) that order from us.
And maybe 40 of those companies also have online stores (admin accounts) with us.
An online store has a customer list of users that belong to their store, and the admin account lets them create and manage customers and customer orders.
So the customer shops, and when finished the order goes to the company.
The company verifies the order (combines orders to save shipping if they want) and then send it(/part of it) to us or fill it(/part of it) from their inventory.
We pack their order at our warehouse and ship it to the address on the order.
And we invoice the company.
The company then settles payment with their customer. (we never bill a customer directly)
Hopefully that wasn't too convoluted...
So again, we never bill a 'customer' directly. But in our current system, we store all accounts (ordering, admin, AND customers) in the same way.
While considering the redesign, I've questioned if this is the most logical approach. And I was thinking of storing our billable accounts (ordering and admin) in an accounts table and customers in a separate customers table.
The way I was thinking of setting this up was, our accounts have an accountID XXXXX, while users have a similar userID YYYYY, but are identified by a composite key of the two (XXXXX-YYYYY)
So company A's first customer is AAAAA-000001 and company B's BBBBB-00001. This seems fine when I think about things like customer orders being billed to their parent company, and displaying all of a companies customers, etc.
But is it a bad idea to have a customer table where customers non-unique customerIDs, even if that isn't the Primary Key?
I know I could make it work, but is it suboptimal when doing something like a customer_address table that relates a customerID and an addressID? Wouldn't it then need to use an accountID + customerID right?
Originally I was thinking they would all be accounts, and the account number would just be structured that way AAAAA-00000 being the admin account, AAAAA-00001 being customer 1, and so one.
But that brings me back to, should our accounts table treat our clients/billable accounts and their customers the same?
Sorry if this question is kind of all over the place. I think that demonstrates how unsure I am of how it should all be structured...
Any input would be greatly appreciated.
Within a project, I have to store the daily availability of different meeting rooms. So let's suppose around 1.000.000 meeting rooms, where each meeting room is in a city, and a city could have hundreds of meeting rooms.
I would also like to be able to make SELECT Queries entering the city and the availability that I need, so I would like to get a list of the available meeting rooms for a day, or set of continues days, in a concrete city.
I have one table called "MeetingRoom", when I store the city and the name of the meeting room, but my design question is how to design the availability part:
Is it better in terms of performance to have a binary array that stores the 365 days of the year with a '1' or '0' according to the availability of the meeting room?
Is it better in terms of performance to have another table called "Availability" that stores a DATE and a BIT with the availability, and then JOIN both tables for each meeting room that exists in a city?
Could it better another option I don't have in mind?
I wonder what querying time would be optimal having around 1.000.000 meeting rooms, and searching for the meeting rooms in a city and available for concrete days. Is it crazy about thinking in database responses below 100 ms?
Some colleagues told me that I should also consider to migrate to MongoDB or NoSQL approach. I don't know if a change of DB could fit better with my issues, or if it don't. Any comment about this?
Thank you very much for the help!!
I don't know if this will help, but if it doesn't, please write me to delete the answer.
Instead of these options you may want to consider that in the "Availability" table to store only the id(surrogate) of the room and the date on which it is reserved. So when you select the data and join both tables you will get only the reserved rooms. I personally think that there is no point of storing all of the room-date relations with status.
Moreover, to improve the performance you can create non-clustered index on the City column for instance.
Please don't fill your database with lots of rows which are default values.
so you don't store availability of a meeting room, you store booking of a meeting room.
primary key of booking table is date and room id , other fields are who booked this room, when booking was asked, a booking id...
If it is possible to book meeting room for part of the day then primary key should be start_date and room id, end date is stored in another field of the table.
I am having a database design issue and i'm still pretty new to MySQL so I thought I would ask here. What would be the best way to get data for a chronological feed from multiple tables? For example a user does many things, they vote, comment, rate, ask questions. I save all this information in their respective tables "tblVote", "tblRate" etc, now the tricky part. a user can follow a user or many, so say you follow 3-4 people. Following allows you to see their interactions, voting, rating, commenting, asking questions etc in your feed (like facebook or something similar).
What would be the best way to get all the information from all 5 tables for every person they follow and then sort all of that chronologically? I Am assuming my current method (foreach follower grab all votes, comments, ratings etc and sort all would be terrible)
My working theory, so my working idea is to create a Interaction table, that has a column for the users id, the id of the other tables entry, and a type reference. so for example
User ID | InteractionID | Type
9 1232 Comment
10 80 Rating
9 572 Vote
Then you could just go ahead and grab all Interactions for each of the people they follow, sort that and then say grab the top 10? and query the individual databases to get the full info (time of comment, text of comment etc)
A many to many relationship exists between User and Follower. Since, Follower is also another user, this becomes a recursive many-to-many. When you decompose this relationship, you get a Association table or a gerund.
User_Follower {id, userid_fk, followerid_fk}
Both the userid_fk and followerid_fk are referencing to the User table.
Now, I am assuming you have a One-to-many relationship between User-tblRate, User-tblVote, User-tblPost etc.
So, you can write a join something like this:
select p.postTitle, p.postTag, ...,
c.commentId, c.commentData, ...
from (tblUser u INNER JOIN tblPost p
ON (p.userid = u.userid)) INNER JOIN tblComment c
ON (c.userid =
u.userid)
where u.userid in
(select userid_fk from user_follower where followerid_fk = 100)
orderby p.datetime_col ASC, c.datetime_col ASC
LIMIT 10;
100 is the user you want to get the information for.
The idea is that you just have one association table linking the User and Follower, then use simple joins to get the data for all the followees
I am working on a personal project and needed some guidance with a mySQL database. I am trying to simulate an airlines reservation system where a user has a personal account added to an Accounts db table (with username and password information). Then I have my Flights db table to store all of the available flights. The Flights db table has all of the flights with information (columns) on departure city, arrival city, departure time, arrival time, price, available seats, and seat capacity.
My question is:
When a user books a flight I must update the available seat value (int) in the Flights table. But then I also must add the flight to the user's account in the Accounts table. I am wondering how to handle this in mySQL, do I have to add a new column to the Accounts table with the corresponding flight's table index from the Flight's db table. Then continue adding a booked flight column as a user books flights to keep track of all the flights a user has booked? Is there a better way to update the Accounts table with flights booked information?
All help is very much appreciated.
Honestly, I would probably go about this a little differently. You may think about adding an additional table that tracks seat reservations. Something like:
TABLE: Accounts
ID | First Name | Last Name | Username | Password
TABLE: Flights
ID | DepartureCity | ArrivalCity | DepartureTime | Price | SeatingCapcity
TABLE: Reservations
ID | Account_ID | Flight_ID | SeatNumber
You can then use SQL functions and math to determine the number of seats available on a particular flight and maintain just the Reservations table when making updates. This also links all flights a particular account is associated with and is not "hard coded" to a particular column. (ie: A user can reserve more than one flight)
The best way to achieve this is to introduce a new table Bookings. A possible structure might be
CREATE TABLE Bookings (user_id INTEGER NOT NULL, flight_id INTEGER NOT NULL);
Then you can fetch all flights of a given user by
SELECT f.* FROM Users u
LEFT JOIN Bookings b ON u.id = b.user_id
LEFT JOIN Flights f ON b.flight_id = f.id
WHERE u.id = ?
And count the bookings for a given flight by
SELECT count(*) FROM Flights f
LEFT JOIN Bookings b
WHERE f.id = ?
This structure has several advantages:
You don't have to change the schema if users book more and more flights. Changing the schema of your database is a quite complex an expensive operation. (BTW: There is a maximum column count in MySQL)
You have an point where you can add further fields that are concerned with bookings. Maybe you want to track reservations.
Its more natural to fetch and add data. If you add columns booked_flight_1 booked_flight_2 and so on. You have to check which slot isn't already taken, which gets more and more complex when you consider deletions. Here it as easy as running this
INSERT INTO Bookings (user_id, flight_id) VALUES (1, 2)
If have to check if a given flight is available, it might be better to check this using your program and insert the booking into the database, if it is.
Joins and transactions might be the techniques you will find useful. The MySQL documentation and every good book on relational databases will give you an introduction in this. Your question sounds to me, as a classical instructional example.
I have a database where users enter their interests. I want to find people with matching interests.
The structure of the interest table is
interestid | username | hobby | location | level | matchinginterestids
Let's take two users to keep it simple.
User Joe may have 10 different interest records
User greg may have 10 different interest records.
I want to do the following algorithm
Take Joe's interest record 1 and look for matching hobbies and locations from the interest database. Put any matching interest id's in the matches field. Then go to joe's interest record 2 etc..
I guess what I need is some sort of for loop that will loop through all of joe's intersts and then do an update each time it finds a match in the interest database. Is that even possible in MySQL?
Further example:
I am Dan. I have 3 interests. Each interest is composed of 3 subjects:
Dan cats,nutrition,hair
Dan superlens,dna,microscopes
Dan film,slowmotion,fightscenes
Other people may have other interests
Joe:
Joe cats,nutrition,strength
Joe superlens,dna,microscopes
Moe
Moe mysql,queries,php
Moe film,specialfx,cameras
Moe superlens,dna,microscopes
Now I want the query to return the following when I log in as Dan:
Here are your interest matches:
--- is interested in cats nutrition hair
Joe is interested in cats and nutrition
Joe and Moe are interested in superlens, dna, microscopes
Moe is interested in film
The query needs to iterate through all Dan's interests, and compare 3,2,1 subject matches.
I could do this in php from a loop but it would be calling the database all the time to get the results. I was wondering if there's a crafty way to do it using a single query Or maybe 3 separate queries one looking for 3 matches, one for 2 and one for 1.
This is definitely possible with MySQL, but I think you may be going about it in an awkward way. I would begin by structuring the tables as follows:
TABLE Users ( userId, username, location )
TABLE Interests( interestId, hobby )
TABLE UserInterests( userId, interestId, level )
When a user adds an interest, if it hasn't been added before, you add it to the Interests table, and then add it to the UserInterests table. When you want to check for other nearby folks with similar interests, you can simply query the UserInterests table for other people who have similar interests, which has all that information for you already:
SELECT DISTINCT userId
FROM UserInterests
WHERE interestId IN (
SELECT interestId
FROM UserInterests
WHERE userId = $JoesID
)
This can probably be done in a more elegant fashion without subqueries, but it's what I thought of now.
As per special request from daniel, although it's kind of duplicate but never mind.
The schema explained
TABLE User (id, username, location )
TABLE Interests(id, hobby )
TABLE UserInterest(userId, interestId, level )
Table users has just user data and a primary key field at the start: id.
The primary key field is a pure link field, the other fields are info fields.
Table Interest again has a primary key that is use to link against and some info field
(ehm well just one, but that's because this is an example)
Note that users and interests are not linked in any way whatsoever.
That's odd, why is that?
Well there is a problem... One user can have multiple intrests and intrests can belong to multiple people.
We can solve this by changing to users table like so:
TABLE users (id, username, location, intrest1, intrest2, intrest3)
But this is a bad, really really bad idea, because:
This way only 3 interests per user are allowed
It's a waste of space if many users have 2, 1 or no interests
And most important, it makes queries difficult to write.
Example query for linking with the bad users table
SELECT * FROM user
INNER JOIN interests ON (user.intrest1 = interests.id) or
(user.intrest2 = interests.id) or
(user.intrest3 = interests.id);
And that's just for a simple query listing all users and their interests.
It quickly gets horribly complex as things progress.
many-to-many relationships
The solution to the problem of a many to many relationship is to use a link table.
This reduces the many-to-many relationship into two 1-to-many relationships.
A: 1 userinterest to many user's
B: 1 userinterest to many interests
Example query using a link-table
SELECT * FROM user
INNER JOIN userInterest ON (user.id = userInterest.userID) //many-to-1
INNER JOIN interest ON (interest.id = userInterest.InterestID); //many-to-1
Why is this better?
Unlimited number of interests per user and visa versa
No wasted space if a user has a boring life and few if any interests
Queries are simpler to maintain
Making it interesting
Just listing all users is not very fun, because then we still have to process the data in php or whatever. But there's no need to do that SQL is a query language after all so let's ask a question:
Give all users that share an interest with user Moe.
OK, lets make a cookbook and gather our ingredients. What do we need.
Well we have a user "Moe" and we have other user's, everybody but not "Moe".
And we have the interests shared between them.
And we'll need the link table userInterest as well because that's the way we link user and interests.
Let's first list all of Moe's Hobbies
SELECT i_Moe.hobby FROM interests AS i_Moe
INNER JOIN userInterests as ui2 ON (ui2.InterestID = i_Moe.id)
INNER JOIN user AS u_Moe ON (u_Moe.id = ui2.UserID)
WHERE u_Moe.username = 'Moe';
Now we combine the select for all users against only Moe's hobbies.
SELECT u_Others.username FROM interests AS i_Others
INNER JOIN userinterests AS ui1 ON (ui1.interestID = i_Others.id)
INNER JOIN user AS u_Others ON (ui1.user_id = u_Others.id)
/*up to this point this query is a list of all interests of all users*/
INNER JOIN Interests AS i_Moe ON (i_Moe.Hobby = i_Others.hobby)
/*Here we link Moe's hobbies to other people's hobbies*/
INNER JOIN userInterests as ui2 ON (ui2.InterestID = i_Moe.id)
INNER JOIN user AS u_Moe ON (u_Moe.id = ui2.UserID)
/*And using the link table we link Moe's hobbies to Moe*/
WHERE u_Moe.username = 'Moe'
/*We limited user-u_moe to only 'Moe'*/
AND u_Others.username <> 'Moe';
/*and the rest to everybody except 'Moe'*/
Because we are using INNER JOIN's on link fields only matches will be considered and non-matches will be thrown out.
If you read the query in english it goes like this.
Consider all users who are not Moe, call them U_others.
Consider user Moe, call him U_Moe.
Consider user Moe's Hobbies, call those i_Moe
Consider other users's Hobbies, call those i_Others
Now link i_Others hobbies to u_Moe's Hobbies
Return only users from U_Others that have a hobby that matches Moe's
Hope this helps.