I have another case.
I got the bus with 27 seats
then, if people pick the seat 4, so nobody can take that seat 4.
my question:
how design database contain 27 seats? I guess using looping until 27 with PHP
how to show in form, selection form contain the un-booked seat?
how to prevent if other people take same seat?
thanks.
Database:
Have a BusType table with properties that would include the number of seats,cost,etc.
Have a BusBookedSeats table that will hold a FK relationship to the Bus in question and keep a running total of the number of seats it has remaining and/or booked.
Form:
Query the database and take the number of total seats - the number of booked seats. Add further validation to show the location of the seat.
Prevention:
If the query returns a value greater than 0 (meaning taken in this instance) warn the user that it is taken and inform them to take another seat. Or don't even display the seat to them.
For your database:
You have a table with busses and available seat numbers
You have a table for reservations
You have a table which has a relation with a reservation on a specific seat on a specific bus
How to show the available seats:
Do a query for all reserved seats
Draw a picture of the bus and mark all reserved seats
How to prevent double reservation:
You need some kind of transaction routine but it is hard to tell, when to lock a seat and when to unlock it (e.g. a user doesn't responds for some time). Usually you only reserve it at the last step. So making sure you have not too many steps or the selection is one of the last steps, you reduce the number of conflicts.
These are indeed only some very basic tips, but the whole problem is too complex to anwser it in short. If you have any specific questions you might want to aks them separately.
From a DB Perspective, based on what i understand of your requirments, i would suggest something on these lines :-
Bus Table - containing an entry for each individual bus. Has a column that indicates the seating capacity of this bus.
User Table - containing an entry for each user who can book a seat on a bus.
BusUser Table - transaction table containing a record for seat on a bus eg: if bus X has 27 = seating capacity, this table will have 27 records - each with the corresponding seat number associated with it.
From a UI perspective, you display the bus user contents. When a user selects one of the records on the UI, you associate the user with that record in BusUser table. BusUser - will have a column indicating the user associated with that bus instance.
Thats the general idea. Hope that gives some pointers for you to start off on..
Make sure you have some sort of a primary key which involves the time of the bus leaves etc along with the unique identifier for each bus (composite primary key). You can only have the unique identifier of the bus as that will limit each bus to be only ride once :)
The 27 seats of a bus i think should be handled by your application. Perhaps, insert 27 rows first for each bus and update when someone books a seat. This way, you can let the user perhaps select which seat they want as well. (Should be done from your GUI).
Of course you should have a status for each seat which you can use to find out whether it is reserved or not.
This is a VERY basic idea and I have not included any diagrams or anything of that sort. I hope I have not spoiled your opportunity to design the database on your own :)
A database lie In Sane has suggested is a good idea. Stopping duplicate bookings really isn't that difficult - you just need to choose a method.
Queue system - When people order you'd append them to the tail of a queue and then have a seperate script to pull people from the head. You'd then be able to evaluate each order at a steady pace, one by one.
Database level - If you're going to use MySQL you'd probabaly be better off using a engine like InnoDB which supports transactions (introduction: http://www.databasejournal.com/features/mysql/article.php/3382171/Transactions-in-MySQL.htm)
Related
Assumptions
If A is a friend of B, B is also a friend of A.
I searched for this question and there are already lots of questions on Stack Overflow. But all of them suggest the same approach.
They are creating a table friend and have three columns from, to and status. This serves both purposes : who sent friend request as well as who are friends if status is accepted.
But this means if there are m users and each user has n friends, then I will have mn rows in the friends table.
What I was thinking is to store friends list in a text column. For every user I have a single row and a friends column which will have all accepted friends' IDs separated by a character, say | which I can explode to get all friends list. Similarly, I will have another column named pending requests. When a request is accepted, IDs will move from pending requests to friends column.
Now, this should significantly reduce the entries in the table and the search time.
The only overhead will be when I will have to delete a friend, I will have to retrieve the friend string, search the ID of the friend to be deleted, delete the ID and update the column. However, this is almost negligible if I assume a user cannot have more than 2000 friends.
I assume that I will definitely be forgetting some situations or this approach will have certain pitfalls. So please correct if so.
The answer is NO! Do not try to implement this idea - its complete disaster.
I am going to describe more precise why:
Relations. You are storing just keys separeted with |. What if you want to display list with names of friends? You will have to get list, explode it and make another n queries to DB. With relation table from | to | status you will be able to do that with one JOIN.
Deletions. Just horrible.
Inserts. For every insert you will need to do SELECT + UPDATE instead of INSERT.
Types. You should keep items in DB as they are, so integers as integers. Converting ints into string and back could cause some errors, bugs etc.
No ORM support. In future you will probably leave plain PHP for some framework. Take in mind that none of them will support your idea.
Search time?
Please do some tests. Search with WHERE + PRIMARY KEY is very fast.
I'm a bit new to coding in general and seem to be struggling to wrap my mind around how to store data effectively for my application. (I'm attempting this in Laravel, with mySql)
I realise this question might lean towards being opinion-specific, but I am really looking for obvious pointers on false assumptions I have made, or a nudge in the direction of best-practices.
I will be tracking a number of messages, as if they were credits in a bulk email management system. One message-batch could use an undetermined number of credits to fire off a full batch of messages.
Groups of users will be able to send messages if they have credits to do so, One solution I have thought of is to have a table: id, user_group_id, debt/credit, reference_code - Where user_group_id would be linked to the group to which the user belongs, the debit/credit column could hold a positive or negative number (of a message related transaction), and the reference_code would track the type of transaction. Debits/Credit transactions would come about where the user_group account received new credits (purchased block of new credits), or in the case of a debits example, where batches of messages had been sent.
All this background leads to my question .. I still don't hold a single value for the available number of credits a user_group has. Before being able to send a new batch, should I be running a database query each time that sums all the "accounting" of positive and negative transactions to determine whether a user is "in the black" to be able to send further message batches, or should I have an additional table and keeps the result of their available credits total separately?
If I do store the total-available-credits value by itself, when should this single value be updated, at the end of every message-related task my application performs ? *user adds new credits, update total - user sends batch, update total.. etc.
This is an interesting question. Opinionated as you pointed out but nonetheless interesting. Database design is not my strong suit but here is how I would do it.
First, ensure integrity with INNODB tables and foreign key constraints. I would keep the total remaining credits each user group has in the user group table. You cold then create a transaction table with a Transaction ID, the User Group ID, and the credits used for that transaction so that you could follow each user group's transaction history.
Just a thought. Like I said, I'm by no means an expert. It may be useful however, to have a log of some sort so that you could verify transactions later in case of a credit discrepancy. You could always use this later to recalculate the remaining credits to ensure the numbers align.
Since these transactions may be important for credit/billing purposes, you may also want to turn off MySQL's auto commit and use the commit and rollback features to ensure your data stays in tact in case of an error.
" should I be running a database query each time that sums all the "accounting" of positive and negative transactions to determine whether a user is "in the black" to be able to send further message batches "
YES
I have a PHP application and I need to store black list data. My site members will add any user to his/her black list. So they won't see the texts of that users.
Every user's black list is different.
A user can have 1000-1500 users in his/her black list.
User can add/remove anybody from his/her list.
Black list will have member's id and black listed people's ids.
I'm trying to design database table for this. But I couldn't be sure about how can structure be ?
I have 7-8 MySQL tables but none of them is like this.
Way 1:
--member ID-----black listed people (BLOB)
-----------------------------------------
--1234----------(Some BLOB data)---------
--6789----------(Some BLOB data)---------
I can serialize blacklisted people's IDs and save them inside a BLOB data column. When a user want to edit his/her list, I get BLOB data from table, remove unwanted ID and update column with new data. IT seems like a bit slow operation when a user has 1k-2k IDs.
Way 2:
--member ID----black listed ID--------
--------------------------------------
--1234---------113434545--------------
--1234---------444445454--------------
--1234---------676767676--------------
--6789---------534543545--------------
--6789---------353453454--------------
In this way, when a user wants to see his/her black list I give them all users in "black listed ID" column. When editing I add/remove new rows to table. This operation is fast but the table can be huge in time.
Way 3:
--member ID----113434545----444445454----676767676---534543545-----353453454
----------------------------------------------------------------------------
--1234--------yes------------yes------------yes------------no------no-------
--6789--------no-------------no-------------no-------------yes------yes------
Yes shows black listed, No shows not black listed. I create new column for each black listed person and update that column when a user adds a person or removes it.
Way 4:
???
These are my ideas. I really appreciate if you can offer me a better one?
Thank you.
What you are creating is a so-called 1 to n relation table.
3rd version
The 3rd version would require to have n rows x n columns, where n is the amount of registred users. InnoDB has a limit of 1000 columns, breaking your logic as soon as 1001st. user registers. Not to mention that you don´t want to ALTER TABLE for every new user. Forget that.
1st version
The first solution is really slow: BLOB data won´t be really idexed, it tends to get into a second page (file on harddisk, effectively doubeling disk I/O), it has massive datasize overhead, sorting and grouping won't happen in RAM, and you have no efficient way for backwards search (how many people did blacklist user xy?)... as a general advise, try to avoid BLOB untill absolutely necesarry.
2nd version
The second solution is the way to go. MySQL is optimized for stuff like that, and a table with 2 numeric, indexed rows is really fast.
Table design
I would create a table consisting of
blocker_id | blocked_id
and no separate primary key. Instead I would create a 2-column-primary-key with blocker beeing the first column and blocked the second. That way you save a B-Tree (expensive to create index) and can search fast for both all blockeds from a blocker (using half of the key) and for the existence of a single combination. (That will be most relevant for filtering posts, and should be optimized for.)
I think you should make the blacklist like way 2:
black_list_id | blocker | blocked
So when you want to take whom a user blocks you would get it by SELECT * FROM black_list_table WHERE blocker = :user_id.
To get who is blocking the user you get SELECT SELECT * FROM black_list_table WHERE blocked = :user_id.
You can easily take how many people block user, how many blocked people user has, and moreover, you can set indices on all columns and get other users' data using JOIN statements.
I want to improve the speed of a notification board. It retrieves data from the event table.
At this moment the events MySQL table looks like this
id | event_type | who_added_id | date
In the event table I store one row with information regarding a particular event. Each time a users A asks for new notifications, the query runs through the table and looks if the notifications added by the user B suit him (they have to be friends, members of the same groups, have previously chatted).
Table events became big, because of the bulky query the page loads slow.
I'm thinking of changing entirely this design and, instead of adding one event row and then compare if the user's event suits or not, to add as many rows as interested users. I would change the table events structure as follows:
id | event_type | who_added_id | forwho_id | date
Now, if user B creates an event which interests other 50 members, I create 50 rows with the same information and in the 'forwho_id' field I mention those 50 members which must get this notification.
I think the query will become much more simple and it will take less time to search through it.
How do you think:
1. Is this a good approach in storing such kind of data or we should avoid duplicate data at any cost?
2. How do you think the events table will behave if the number of interested users will be not 50 but hundreds?
Thank you for reading this and I hope I made myself understandable.
Duplicated data is not "bad", and it's not to be "avoided at all cost".
What is "bad" is uncontrolled redundancy, and the kind of problems that come up when the logical data model isn't third normal form. It is acceptable and expected that an implementation will deviate from a logical data model, and introduce redundancy for performance.
Your revised design looks appropriate for your needs.
I have many fields which are multi valued and not sure how to store them? if i do 3NF then there are many tables. For example: Nationality.
A person can have single or dual nationality. if dual this means it is a 1 to many. So i create a user table and a user_nationality table. (there is already a nationality lookup table). or i could put both nationalities into the same row like "American, German" then unserialize it on run-time. But then i dont know if i can search this? like if i search for only German people will it show up?
This is an example, i have over 30 fields which are multi-valued, so i assume i will not be creating 61 tables for this? 1 user table, 30 lookup tables to hold each multi-valued item's lookups and 30 tables to hold the user_ values for the multi valued items?
You must also keep in mind that some multi-valued fields group together like "colleges i have studied at" it has a group of fields such as college name, degree type, time line, etc. And a user can have 1 to many of these. So i assume i can create a separate table for this like user_education with these fields, but lets assume one of these fields is also fixed list multi-valued like college campuses i visited then we will end up in a never ending chain of FK tables which isn't a good design for social networks as the goal is it put as much data into as fewer tables as possible for performance.
If you need to keep using SQL, you will need to create these tables. you will need to decide on how far you are willing to go, and impose limitations on the system (such as only being able to specify one campus).
As far as nationality goes, if you will only require two nationalities (worst-case scenario), you could consider a second nationality field (Nationality and Nationality2) to account for this. Of course this only applies to fields with a small maximum number of different values.
If your user table has a lot of related attributes, then one possibility is to create one attributes table with rows like (user_id, attribute_name, attribute_value). You can store all your attributes to one table. You can use this table to fetch attributes for given users, also search by attribute names and values.
The simple solution is to stop using a SQL table. This what NoSQL is deigned for. Check out CouchDB or Mongo. There each value can be stored as a full structure - so this whole problem could be reduced to a single (not-really-)table.
The downside of pretty much any SQL based solution is that it will be slow. Either slow when fetching a single user - a massive JOIN statement won't execute quickly or slow when searching (if you decide to store these values as serialized).
You might also want to look at ORM which will map your objects to a database automatically.
http://en.wikipedia.org/wiki/List_of_object-relational_mapping_software#PHP
This is an example, i have over 30
fields which are multi-valued, so i
assume i will not be creating 61
tables for this?
You're right that 61 is the maximum number of tables, but in reality it'll likely be less, take your own example:
"colleges i have studied at"
"college campuses i visited"
In this case you'll probably only have one "collage" table, so there would be four tables in this layout, not five.
I'd say don't be afraid of using lots of tables if the data set you're modelling is large - just make sure you keep an up to date ERD so you don't get lost! Also, don't get caught up too much in the "link table" paradigm - "link tables" can be "entities" in their own rights, for example you could think of the "colleges i have studied at" link table as an "collage enrolments" table instead, give it it's own primary key, and store each of the times you pay your course fees as rows in a (linked) "collage enrolment payments" table.