简体   繁体   中英

What is best approach to creating SQL tables to easily query in the long run?

I'm currently working on a project for a client. His needs have changed and so my database structure has to change too.

My client runs a tour operator business and he registers many people per day. What he wants to achieve is to be able to group passengers. So in the admin interface, you click the passengers you want to group, and voila. They're in a group.

In each group, you can assign extras eg lunch, drinks, hire gear so staff members can map a price to that group.

The following is the what I need, my questions is how do I build the SQL tables from this. I'm currently reading through one-many many-many relationships, foreign keys etc. In the long run I want to be able to query the database without any issues, had many issues in my past experience:

Groups
gp_ID    customer_ID    leader    fare_Type    dependant_Fare_Child    dependant_Fare_Adult

Tour_Extras
TE_ID    TE_Name

Tour_Extra_Price
TE_ID    TE_Price    fare_ID

Fare_Type
fare_ID    fare_Name

Group_Extras
gp_ID    TE_ID    quantity    fare_ID

Groups Contains all the passengers in that group. There will only be one leader and the customer_ID will be used as a reference to another table for all contact personal for that passenger. The fare_Type will be an int which will reference the Fare_Type table. the dependant_Fare_Ch and adult are integers too. this will determine how many children and children charged at adult prices are assigned to the dependant.

Tour_Extras holds types of extras group can have. eg lunch, gear hire

Tour_Extra_Price holds prices for particular extra as well as fare_ID which will determine what price to charge (child, adult, senior)

Fare_Type holds the fare_Id and the names (child, adult, senior)

Group_Extras This is the biggy. It will reference the groups, tour_extra and possible the Fare_Type table. This will be used to determine what the total amount will be for that particular group. For eg:

gp_ID TE_ID quantity fare_ID
  1     1      3       1

For group with an id of 1, they have chosen TE_ID of 1 (eg lunch) and purchased quantity (3) and will be charged to fare_ID 1 (eg child)

This may be of help to some people:

Tour_Extras can have many Tour_Extra_Price

Tour_Extra_Price can have one Fare_Type

Group_Extras can have many Groups, Tour_Extras and/or Fare_Type (unsure whether to link with Fare_Type directly, or go through Tour_Extras, then Tour_Extra_Price, then Fare_Type)

I have other questions like are foreign keys needed? Is it best to have primary keys on the Group_Extras table and foreign keys on the other tables?

Apologies for the long post but I want to exhaust all options and do my research before diving into this project.

ps I won't be back on for a few hours. So ask questions please and I'll answer them within 12 hours.

Your database structure is generally fine for the requirements that you described. I would suggest you add a "Group" table which you could use for common attributes shared for the group member, eg the ID, a name for the group if necessary, or a timestamp. You could also set the ID of the leader here directly, instead of having a "leader" flag in each row of the groups table.

Other than that I would make one change; since you are using MySQL you might choose to use an ENUM field for the fareType instead of a Fare_Type table (since I assume the 3 values are unlikely to change - if they change, you can easily add more values). This would simplify your queries since you have to do one less join, and also makes your database a bit more readable while debugging. Academically your solution is correct, I would just change this to make your life a bit easier (and make the database more readable). Of course, if the users want to edit the fareTypes themselves you have to keep it as a seperate table.

Technically you don't need any foreign keys - your application will work just fine if you only add primary keys and keep the relations in mind in your update/deletion/insertion logic. If you add foreign keys, it will add constraints on your tables so that their integrity can't be violated. Eg if you want to delete a Tour_Extra, you would first have to make sure that no other table has a reference on it, or you would get a constraint error. Although things have improved, I'm not really keen to work with foreign keys in MySQL, there used to be a lot of problems. If you choose to use them, you need to set your tables to the InnoDB database engine in any case.

Your primary keys should be pretty clear:

  • Group -> gp_ID (auto_increment)
  • Groups -> gp_ID, customer_ID
  • Tour_Extras -> TE_ID (auto_increment)
  • Tour_Extra_Price -> TE_ID, fareType (enum)
  • Group_Extras -> gp_ID TE_ID, fareType (enum)

And the foreign keys, if you choose to assign them:

  • Groups -> gp_ID references Group.gp_ID, customer_ID references customer.customer_ID
  • Tour_Extra_Price -> TE_ID references Tour_Extra.TE_ID
  • Group_Extras -> gp_ID references Group.gp_ID, (TE_ID, fareType) references (Tour_Extra_Price.TE_ID, Tour_Extra_Price.fareType)

Obviously we live some hours apart from each other, so the question-answer round trips in the requests comment section take too much time. So instead of asking more one-per-day-questions, here are my thoughts:

To start with: What does a customer_id actually represent? Do you have customers stored, so you recognize them when they repeatedly book tours? It doesn't seem so to me (and anyway, what would you gain from this?). From what I see, it looks more like a tour booking to me. So every time Mr. Miller books a tour he gets a new customer_id. But if so, doesn't the customer_id represent his complete booking already? You wouldn't need a customer_id for Mrs. Miller, because she would be included in that booking.

So what I see is a booking. This consists of one person's name and contact details (Mr. Miller in my example) plus number of travelers. That would be:

table booking

  • booking_id
  • tour_id
  • name
  • address
  • phone

table booking_passengers

  • booking_id
  • fare_type_id (adult / child / senior)
  • quantity (how many of that type in that booking

Data should always be in the tables, not in a table name or column name. So you would not have columns like dependant_Fare_Child and dependant_Fare_Adult, but a table booking_passengers with a column fare_id instead, so you can join based on the ID.

So the booking (or customer as you call it) already represents a group. Do you need more details on the co-passengers, then replace booking_passengers with a table that hold one record per passenger:

table booking_passenger

  • booking_id
  • fare_type_id (adult / child / senior)
  • name
  • age

Your structure for tour extras looks fine. As I call your customer or group a booking, my table would be:

table booking_extras

  • booking_id
  • tour_extra_id (lunch / gear / ...)
  • fare_type_id (adult / child / senior)
  • quantity

For the tour prices I assume such a table, btw:

table tour_price

  • tour_id
  • fare_type_id (adult / child / senior)
  • price

Primary keys in above tables are italic. You should use foreign keys. They exist to guarantee data consistency, eg not to have passengers without a booking. Database people would always take it for granted to have foreign keys in a relational database and rely on their existence as much in regard to data consistency as to available indexes. So the table booking_extras would have a primary key booking_id + tour_extra_id + fare_type_id. You would have a foreign key to tables booking via booking_id, tour_extra via tour_extra_id, and fare_type via fare_type_id.

Hope this helps. If I misunderstood anything, just tell me so in comments and I will hopefully find the time to adjust my answer accordingly.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM