One or two tables: that is the quest*on - mysql

I'm trying to setup a database schema for a company which works as a middle man (selling items collected from vendors to buyers).
Both of these entities (vendors and buyers) can be generalized as a client - they both have very similar attributes (name, email, password, address, etc...) and multiple other entities depend on this. For example invoices are generated for buyers and settlements (different type of paperwork) are generated for vendors. The thing is that one person (a client) can by buyer and vendor in the same time.
The dilema I'm having is how to setup the database structure for this?
At the moment I'm more in favor of having both vendors and buyers in one table and distinguish between them using something like roles column. Thanks to this approach I would avoid the data redundancy and I could still create views to easily separate vendors from buyers to the outside world.
Am I thinking about this correctly? How would you typically solve this situation? Would it be better to use two separate tables?
Thank you for your advice and experiences :)

If you know the usecases, think about, what could be a rough solution. But that is quite dangerous, at the end sometimes the ingenious datamodel becomes too complicated to understand and maintain.
How important is it to decide now, will your datamodel or organization be fit for a later change?. Can you be agile? Then implement, what is best for your current usecases, nothing more!
btw.
if there is a 1 to 2 relationsship between person and role, you should factor out the role, not duplicate the data, or create two attributes, isBuyer and isVendor, or put in these attributes references to the buyer- and vendor-specific data, if there is any.

Related

ER Diagram, Physical Data Model Relations

I am trying to create a very simple database Supermarket management system.
And it seems that I am having a problem with how relations work between entities, I am using PowerDesigner to create the ERD and then generate everything from it(LDM, PDM, OOM). Is this a bad idea?.
Now for my main problem It's between these 3 tables:
Employee(Cashier)
Customer
Orders(Receipt).
The way I did it is:
The customer gather the products he wants to buy and present it to the employee, then the employee gets the order for the customer from the machine, so:
There is a relation between the Customer and the Employee (Many to Many) : each customer can request_order from one or more Employee and each Employee can get_order to one or more Customer.
There is a relation between the Employee and the Orders (1 To Many) : each Employee can get one or more orders, each order is fetched by one employee.
The problem is if I want to know the customer related to that specific order......I can't.
How do I fix this? How can I get the specific order that customer made.
I am still very new to this, so sorry for any obvious mistakes.
I am sticking to the Relational Database context, that you have tagged.
Data Modelling is an iterative process. There is a lot more definition that is needed, before the data model can be complete. Rather than answering the specifics that you request, which would be limited to one iteration; one increment, allow me to provide something more complete, several iterations progressed.
If it is useful, please discuss this data model, and progress it to fulfil all your requirements.
Of course it is too small as an inline graphic. As a PDF Supermarket Data Model.
The Standard for Relational Data Modelling since 1983 is IDEF1X. For those unfamiliar with the Standard, refer to the short IDEF1X Introduction.
I am using PowerDesigner to create the ERD and then generate everything from it (LDM, PDM, OOM). Is this a bad idea?.
PowerDesigner is great. Just ignore the Oracle-specific nonsense, it pushes you into considering the physical far too early.
Skip the ERD, it is brain-dead in the context of the Relational paradigm, and surpassed by IDEF1X, which is specific to that paradigm.
Use the Entity Level display for ERD equivalence.
For small projects you can ignore the academic distinctions {CDM; LDM; PDM; OOM, etc}.
There is actually just one model: it is "conceptual" at the beginning, and you just progress to "logical", and last, when the "logical" is stable, to the "physical".
Understand that the whole process is Logical.
Unfortunately, in PD you have to have separate "models" or files for each.
Now for my main problem It's between these 3 tables:
I have solved that issue. And exposed others.
each customer can request_order from one or more Employee and each Employee can get_order to one or more Customer
each Employee can get_order to one or more Customer
Yes, but that is the overall result. In each shopping or presentation instance:
a customer can request_order from one Employee (Cashier)
a Employee can get_order from one Customer
The problem is if I want to know the customer related to that specific order......I can't. How do I fix this?
Solved: Each Order is Identified by (CustomerId, DateTime), ie. the Customer who created the Order.
Note
Do not mix Process elements (eg. Get_Order) with Data elements (eg. the data model). The two areas are separate, and governed by quite different science. Here we are solving the Data; only the Data; and nothing but the Data. After that, the Process Model is easy.
RecordIds are anti-Relational. They are certainly not needed in a Relational database. Read my other Answers for detailed explanations.
Relational Keys (aka Compound Keys or Composite Keys) are standard fare in a Relational database. They provide far more integrity than a RecordId based file ever can.
You need to be more precise (state the exact sequence) in defining how an Order is created.
Please feel free to comment or ask specific questions.

Database design & normalization

I'm creating a messaging system for a e-learning platform and there are some design concerns that I'd like some feedback on.
First of all, it is important for me and my system to be highly modifiable in the future. As such, maintaining a fairly high normalization across my tables is important.
On to how my system will work:
All members (students or teachers) are part of a virtual classroom.
Teachers can create tasks and exercises in these classrooms and assign them to one or multiple students (member_task table not illustrated).
A student can request help for a specific task or exercise by sending a message to the teachers of the classroom.
Messages sent by students are sent to all the teachers. They cannot address a message to a specific teacher.
Messages sent by teachers can be addressed to one or more students.
Students cannot send messages to other students.
Messages behave like chat, meaning that a private conversation starts between a student and all teachers when they send a message.
Here's the ER diagram I made:
So my question is, is this table normalized properly for my purpose? Is there anything that can be done to reduce redundancy of data across my tables? And out of curiosity, is it in BCNF?
Another question: I don't intend to ever implement delete features anywhere in my system. Only "archiving" where said classroom/task/member/message/whatever is simply hidden/deactivated. So is there any reason to actually use FK?
EDIT: Also, a friend brought to my attention that the Conversations table might be redundant, and it kinda feels so. Thoughts?
Thanks.
In response to your emphasis on "modifiability" which I'm taking to mean with respect to application and schema evolution I'm actually going to suggest a fairly extreme solution. Before that some notes some aspects you've mentioned. First, foreign keys represent meaningful constraints in your data. They should always be defined and enforced. Foreign keys are not there just for cascading delete. Second, the Conversations table is arguably redundant. It would make sense if you had a notion of "session" of chat which would correspond to a Conversation. Otherwise, you just have a bunch of messages throughout time. The Conversation table could also enable a many-to-many relation between messages and tasks/exercises if you wanted to have chats that simultaneously covered multiple exercises, for example.
Now for the extreme suggestion. You could use 6NF. In particular, you might look at its incarnation in anchor modeling. The most notable difference in this approach is each attribute is modeled as a different table. 6NF supports temporal databases (supported in anchor modeling via "historized" attributes/ties). This means handling situations like a student being associated to a task now but not later won't cause all their messages to disappear. Most relevant to you, all schema modifications are non-destructive and additive, so no old code breaks when you make a change.
There are downsides. First, it's a bit weird, and in particular anchor modeling (somewhat gratuitously?) introduces a bunch of new terms. Second, it produces weird queries for most relational databases which they may not optimize well. This can sometimes be resolved with materialized views. Third, at the physical level, every attribute is effectively nullable. Finally, the tooling and support, while present, is pretty young. In particular, for MySQL, you may only be "inspired by" what's provided on the anchor modeling site.
As far as the actual database model would go, it would look roughly similar. Anchor modeling uses the term "anchor" for roughly the same thing as an entity, and "tie" for roughly the same thing as a relation. For simplicity, dropping the Conversation relation (and thus directly connecting Message to Task), the image would be similar: you'd have an anchor for Classroom, Member, Message, and Task, and a tie replacing Recipient that you might called ReceivedMessage representing the relation of "member received message message". The attributes on your entities would be attribute nodes. Making the message attribute on the Message anchor historized would allow messages to be edited if desired and support a history of revisions.
One concern I have is that I don't see a Users table which will hold all the students and teachers info (login, email, system id, role, etc) but I assume there is something similar in our system?
Now, looking into the Members table: usually students change classes every semester or so and you don't want last semesters' students to receive new messages. I would suggest the following:
Members
=============
PK member_id
FK class_id
FK user_id
--------------
join_date
leave_date
active
role
The last two fields might be redundant:
active: is an alternative solution if you want to avoid using dates. This will become false when a user stops being member of this class. Since there is not delete feature, the Members entry has to be preserved for archive purposes (and historical log).
role: Depends on how you setup Users table and roles in your system. If a user entry has role field(s) then this is not needed. However, this field allows for the same user to assume different roles in different classes. Example: a 3rd year student, who was a member of this class 2 years ago, is now working as TA/LA (teaching/lab assistant) for the same class. This depends on how the institution works... in my BSc we had the "rule": anyone with grade > 8.5/10 in Java could volunteer to do workshops to other students (using uni's labs). Finally, this field if used as a mask or a constant, allows for roles to be extended (future-proof)
As for FKs I will always suggest using them for data consistency. Things can get really ugly really fast without FKs. The limitations they impose can be worked around and they are usually needed: What is the purpose of archiving a message with sender_id if the sender has been deleted by accident? Also, note that in most systems FKs are indexed which improves the performance of queries/joins.
Hope the above helps and not confuse things :)

Improving my Database Design for future scalability

Well, I am working on a project which might involve thousands of users & I don't have much experience in databases especially when it involves relationships between entities.
Let me explain my scenario. First there's an User who can login into our system using his credentials. We have a module in our system, which will enable him to create Projects. So that brings a relationship between User table & Projects table.
Now there's another module, namely Team Creation Module, it does what it says. Out of the list of available members, he can pick who he likes and add them to a team. So there are tables for that Members & Team. Furthermore, a member can be a part of many teams and a team can have many members & a "User" can be member as well.
I have a designed the database myself but I am not sure if it is good or bad one. Moreover, I would really appreciate if someone can point me to good tutorials which shows how to insert or update into tables involving relationships.
Here's my design till now:
Update
After a discussion with someone on IRC, I came up with a revised design. I merged "User" & "Members" table as User is also a Member.
My question still remains the same, Am I on right track?
It's great that you're thinking long-term, but your solution won't work long-term.
This is not the first time this sort of thing has been tried before. Rely on the wisdom of those that have messed up before. Read data modeling pattern books.
Abstract and Normalize. That's how you get to a good long-term solution.
At least read up on The Party Model. A group and individual are actually the same (abstract) thing.
Put actually different things in different tables. An Address and Member don't belong in the same table.
"Am I on the right track" is not a useful question - we have no way of telling, because it depends on where you are headed.
A couple of things:
it's a good idea to name the relation columns after the relationship. For instance, in the first diagram, the "owner" of the project should not be called users_user_id - that's meaningless. Call it "owner_id" or something that meaningfully describes the relationship between the project and members table.
in the second diagram, you appear to have a "many to many" relationship between members and projects in the members table - but there's no efficient way of storing the id of more than one project in the members table. You need to factor that out into a joining table - projects_members, for instance, just like you did with teams_members.
the "teams_members" table has a primary key called tm_id. A purist would tell you this is wrong - the unique identifier for that table should be the combination of member_id and team_id. You don't need another unique identifier - and in fact it's harmful, because you must guarantee uniqueness of the member_id and team_id combination.
As Neil says, you probably want to start reading up on this. I can recommend 'Database Systems: Design, Implementation, and Management' by Coronel et al.

Implementing Comments and Likes in database

I'm a software developer. I love to code, but I hate databases... Currently, I'm creating a website on which a user will be allowed to mark an entity as liked (like in FB), tag it and comment.
I get stuck on database tables design for handling this functionality. Solution is trivial, if we can do this only for one type of thing (eg. photos). But I need to enable this for 5 different things (for now, but I also assume that this number can grow, as the whole service grows).
I found some similar questions here, but none of them have a satisfying answer, so I'm asking this question again.
The question is, how to properly, efficiently and elastically design the database, so that it can store comments for different tables, likes for different tables and tags for them. Some design pattern as answer will be best ;)
Detailed description:
I have a table User with some user data, and 3 more tables: Photo with photographs, Articles with articles, Places with places. I want to enable any logged user to:
comment on any of those 3 tables
mark any of them as liked
tag any of them with some tag
I also want to count the number of likes for every element and the number of times that particular tag was used.
1st approach:
a) For tags, I will create a table Tag [TagId, tagName, tagCounter], then I will create many-to-many relationships tables for: Photo_has_tags, Place_has_tag, Article_has_tag.
b) The same counts for comments.
c) I will create a table LikedPhotos [idUser, idPhoto], LikedArticles[idUser, idArticle], LikedPlace [idUser, idPlace]. Number of likes will be calculated by queries (which, I assume is bad). And...
I really don't like this design for the last part, it smells badly for me ;)
2nd approach:
I will create a table ElementType [idType, TypeName == some table name] which will be populated by the administrator (me) with the names of tables that can be liked, commented or tagged. Then I will create tables:
a) LikedElement [idLike, idUser, idElementType, idLikedElement] and the same for Comments and Tags with the proper columns for each. Now, when I want to make a photo liked I will insert:
typeId = SELECT id FROM ElementType WHERE TypeName == 'Photo'
INSERT (user id, typeId, photoId)
and for places:
typeId = SELECT id FROM ElementType WHERE TypeName == 'Place'
INSERT (user id, typeId, placeId)
and so on... I think that the second approach is better, but I also feel like something is missing in this design as well...
At last, I also wonder which the best place to store counter for how many times the element was liked is. I can think of only two ways:
in element (Photo/Article/Place) table
by select count().
I hope that my explanation of the issue is more thorough now.
The most extensible solution is to have just one "base" table (connected to "likes", tags and comments), and "inherit" all other tables from it. Adding a new kind of entity involves just adding a new "inherited" table - it then automatically plugs into the whole like/tag/comment machinery.
Entity-relationship term for this is "category" (see the ERwin Methods Guide, section: "Subtype Relationships"). The category symbol is:
Assuming a user can like multiple entities, a same tag can be used for more than one entity but a comment is entity-specific, your model could look like this:
BTW, there are roughly 3 ways to implement the "ER category":
All types in one table.
All concrete types in separate tables.
All concrete and abstract types in separate tables.
Unless you have very stringent performance requirements, the third approach is probably the best (meaning the physical tables match 1:1 the entities in the diagram above).
Since you "hate" databases, why are you trying to implement one? Instead, solicit help from someone who loves and breathes this stuff.
Otherwise, learn to love your database. A well designed database simplifies programming, engineering the site, and smooths its continuing operation. Even an experienced d/b designer will not have complete and perfect foresight: some schema changes down the road will be needed as usage patterns emerge or requirements change.
If this is a one man project, program the database interface into simple operations using stored procedures: add_user, update_user, add_comment, add_like, upload_photo, list_comments, etc. Do not embed the schema into even one line of code. In this manner, the database schema can be changed without affecting any code: only the stored procedures should know about the schema.
You may have to refactor the schema several times. This is normal. Don't worry about getting it perfect the first time. Just make it functional enough to prototype an initial design. If you have the luxury of time, use it some, and then delete the schema and do it again. It is always better the second time.
This is a general idea
please donĀ“t pay much attention to the field names styling, but more to the relation and structure
This pseudocode will get all the comments of photo with ID 5
SELECT * FROM actions
WHERE actions.id_Stuff = 5
AND actions.typeStuff="photo"
AND actions.typeAction = "comment"
This pseudocode will get all the likes or users who liked photo with ID 5
(you may use count() to just get the amount of likes)
SELECT * FROM actions
WHERE actions.id_Stuff = 5
AND actions.typeStuff="photo"
AND actions.typeAction = "like"
as far as i understand. several tables are required. There is a many to many relation between them.
Table which stores the user data such as name, surname, birth date with a identity field.
Table which stores data types. these types may be photos, shares, links. each type must has a unique table. therefore, there is a relation between their individual tables and this table.
each different data type has its table. for example, status updates, photos, links.
the last table is for many to many relation storing an id, user id, data type and data id.
Look at the access patterns you are going to need. Do any of them seem to made particularly difficult or inefficient my one design choice or the other?
If not favour the one that requires the fewer tables
In this case:
Add Comment: you either pick a particular many/many table or insert into a common table with a known specific identifier for what is being liked, I think client code will be slightly simpler in your second case.
Find comments for item: here it seems using a common table is slightly easier - we just have a single query parameterised by type of entity
Find comments by a person about one kind of thing: simple query in either case
Find all comments by a person about all things: this seems little gnarly either way.
I think your "discriminated" approach, option 2, yields simpler queries in some cases and doesn't seem much worse in the others so I'd go with it.
Consider using table per entity for comments and etc. More tables - better sharding and scaling. It's not a problem to control many similar tables for all frameworks I know.
One day you'll need to optimize reads from such structure. You can easily create agragating tables over base ones and lose a bit on writes.
One big table with dictionary may become uncontrollable one day.
Definitely go with the second approach where you have one table and store the element type for each row, it will give you a lot more flexibility. Basically when something can logically be done with fewer tables it is almost always better to go with fewer tables. One advantage that comes to my mind right now about your particular case, consider you want to delete all liked elements of a certain user, with your first approach you need to issue one query for each element type but with the second approach it can be done with only one query or consider when you want to add a new element type, with the first approach it involves creating a new table for each new type but with the second approach you shouldn't do anything...

MySQL database model for signups with and without addresses

I've been thinking about this all evening (GMT) but I can't seem to figure out a good solution for this one. Here's the case...
I have to create a signup system which distinguishes 4 kinds of "users":
Individual sign ups (require address info)
Group sign ups (don't require address info)
Group contact (require address info)
Application users (don't require address info)
I really cannot come up with a decent way of modeling this into something that makes sense. I'd greatly appreciate it if you could share your ideas.
Thanks in advance!
Sounds like good case for single table inheritance
Requiring certain data is more a function of your application logic than your database. You can definitely define database columns that don't allow NULL values, but they can be set to "" (empty string) without any errors.
As far as how to structure your database, have two separate tables:
User
UserAddress
When you have a new signup that requires contact info, your application will create records in both tables. When a new signup doesn't require address info, your application will only create a record in the User table.
There are a couple considerations here: first, I like to look at User/Group as a case of a Composite pattern. It clearly meets the requirement: you often have to treat the aggregate and individual versions of the entity interchangeably (as you note). Implementing a composite in a database is not that hard. If you are using an ORM, it is pretty simple (inheritance).
On the other part of the question, you always have the ability to create data structures that are mostly empty. Generally, that's a bad idea. So you can say 'well, in the beginning, we don't have any information about the User so we will just leave all the other fields blank.' A better approach is to try and model the phases as if they were part of an FSM. One of the clearest ways to do this in this particular case is to distinguish between Users, Accounts and some other more domain-specific entity, e.g. Subscriber or Customer. Then, I can come and browse using User, sign up and make an Account, then later when you want address and other personal information, become a subscriber. This would also imply inheritance, and you have the added benefit of being able to have a true representation of the population at any time that doesn't require stupid shenanigans like 'SELECT COUNT(*) WHERE _ not null,' etc.
Here's a suggestion from my end after weighing pro's and con's on this model. As I think the ideal setup is to have all users be a user entity that belong to a group without differentiating groups from individuals (except of course flag a group contact person and creating a link with a groups table) we came up with the alternative to copy the group contact user details to the group members when they group is created.
This way all entities that actually are a person will get their own table.
Could this be a good idea? Awaiting your comments :)
I've decided to go with a construction where group members are separated from the user pool anyway. The group members eventually have no relation with a user since they don't require access to mutating their personal data, that's what a group contact person is for. Eventually I could add a possibility for groups to have multiple contact persons, even distinguishing persons that are or are not allowed to edit any member data.
That's my answer on this one.