I am designing a database having the following entities :
Student_detail : has id as PK and rest some attributes.
Event : Has the details about different events. event_no is PK. (there are about 32 events)
Participates_in : is a relation between student_detail and event, has both their PKs as FKs.
Team_with : this is a relation from student_detail table to itself, it has 8 participant columns, one team_id column, one for_event_no column(FK to event_no). All the participant columns are FKs to student_detail.id.
One row of this column indicates a team for a specific event.
The number 8 because, the max team size in all events is 8.
Events have variable number of allowed team sizes.
I devised the team_with table in order to avoid creating 30 different tables for different event.
Due to this, query length is increasing. Is this good design? I would like suggestions for this.
Do all members of a team have equal membership? If there were 8 fixed roles in a team, I would agree with your design. If not, I suggest:
teams (team_id PK, for_event_no FK)
team_members (team_id PK/FK, student_detail_id PK/FK)
However, enforcing a maximum team size of 8 could be more difficult. I don't see this as a significant problem since you say different events allow different team sizes, so the limit of 8 could be incorporated into that mechanism, however it's implemented.
What's the difference between participation in an event and membership of a team associated with the event? There's already a relation between Event and Student_detail - directly in your Team_with, and transitively in my suggestion. Participates_in may be redundant, unless participation is possible without being part of a team.
Related
I am currently designing a database in mariaDb that will be used in a Meteor app (woth sequelize orm) for tracking the attendance of students in a school.
I'm not sure is the most effective way as there are few exceptions on my case:
teachers can move and reorganise their schedule as they please, and also because the student pay for each lesson (and certain type of absence), I can't use a "exclusion way" (eg only record absence, so no record = present)
the most important query needed is attendance per student, and I need to have it every time I open my app for every student.
second most important is a monthly attendance per teacher. (This one is needed on demand)
(not db related) I need to track the students presence by groups of 10 (every lessons they have to pay again)
The estimated starting size is 20 teachers, 250 students, 500 attendance/week, (every student has two lessons) 37 weeks,( max size double students and lessons).
Is running 250 queries (find) on a 20000row table time consuming?
Is on student table having a lesson_counter field that is updated every time an attendance is recorded a good idea?
Many thanks!
UPDATE:
there is a possible optimization to be made? This should represent a base for a possible email and invoice system both towards students and teachers
There are many possible improvements to your design. Let me start by answering your specific questions:
Is running 250 queries (find) on a 20000row table time consuming?
No. On modern hardware, querying 20.000 rows is going to be fast. If you have a decent indexing strategy, the queries should return in 10s of milliseconds.
Is on student table having a lesson_counter field that is updated
every time an attendance is recorded a good idea?
No, it's a bad idea - on the assumption that you want a report for each student showing when they attended or missed a lesson, you have to store that data anyway. Keeping a counter is duplicating that information.
I suggest a design like the following.
An "attendance" and "absence" are logically separate things; you can model them in a single table with a flag. I've modeled them separately because I see them as different things in the business domain, with different attributes (absence has a reason code), and potentially different behaviour (for instance, an absence might have a workflow for sending an email). I prefer to have things that are logically separate in separate tables.
Student
-------
student_id
name
...
Lesson
------
lesson_id
subject
teacher_id (if only one teacher can teach a lesson)
....
enrollment
---------
lesson_id
student_id
start_datetime (or you might have the concept of "term")
end_datetime
lesson_session
-------
lesson_session_id
lesson_id
start_datetime
end_datetime
location
teacher_id (in case more than one teacher can teach a lesson)
attendance
--------
lesson_session_id
student_id
absence
------------
lesson_session_id
student_id
reason (or might be a foreign key to reasons table)
Usually in self realtionship tutorials it is taught in a subordinative way. Eg.: employee X subordinated to employee Y.
I have this scenario bellow where the related players are actually the same person but with different accounts.
So I don't know whether this is right to use self relationship in this case.
(aka: also known as)
aka_id ----> id_player
One player account is not subordinated to another. Players can have multiple accounts but I'm willing to relate them so I can tell they belong to the same person. In the real scenario, there is no master account to relate them to. this is a NON-SUBURDINATIVE scenario.
I thought of not using relationship in this case and insert a random hash key tag to the aka column:
380 | player120 | ae65a3f01a
500 | player430 | ae65a3f01a
The question here is:
Is it right to use self relationships in non-subordinative scenarios?
From the way you describe the problem, you have two entities: players and aka (which I will call nicknames). These are two separate entities, and that usually suggests three tables:
Players
Nicknames
PlayerNicknames
The third table is a junction table that combines the first two. You might be able to put all the information you need about Nicknames in PlayerNicknames -- that is fine. However, if you have a requirement that all nick names be unique, then you definitely want a third table.
My guess is that you have a player name that is automatically a nick name. Great. When you create a player, also create an entry in the nicknames.
I would like to partially implement SCORM standard in my Rails app.
My current data model has the following structure. I have users, I have courses, I have join table user_courses (each row is data for the course started by some user). The latter table has all attributes (columns) that SCORM requires to implement (max score, min score, raw score etc.)
Everything is plain and easy until I get to objectives. It says that SCORM-compliant LMS should support at least 100 objectives. If it were only 4 or 5, I would create 4 or 5 more columns in my user_courses table, but it doesn't have any sense to create 100 as user will probably use 5 to 10.
What is the best way to handle such problem?
How do objectives relate to the current tables?
EDIT:
I'm assuming a course will have a pre-set Objectives and they won't need to track these objectives seperatly per user.
Create table: objectives with objective_id
Create table: course_objectives with course_id, objective_id
You can link course to course_objectives (a course has many objectives) and link objectives to course (an objective can belong to many courses). This will allow you to re-use common objectives between courses. If this is not the case, then you can skip course_objectives and just use objectives to course as, a course can have many objectives.
Does this help?
If you do need to track the progress or status of objectives per user, you'll need another table between user_courses and course_objectives.
-Dan
So I have this application that I'm drawing up and I start to think about my users. Well, My initial thought was to create a table for each group type. I've been thinking this over though and I'm not sure that this is the best way.
Example:
// Users
Users [id, name, email, age, etc]
// User Groups
Player [id, years playing, etc]
Ref [id, certified, etc]
Manufacturer Rep [id, years employed, etc]
So everyone would be making an account, but each user would have a different group. They can also be in multiple different groups. Each group has it's own list of different columns. So what is the best way to do this? Lets say I have 5 groups. Do I need 8 tables + a relational table connecting each one to the user table?
I just want to be sure that this is the best way to organize it before I build it.
Edit:
A player would have columns regarding the gear that they use to play, the teams they've played with, events they've gone to.
A ref would have info regarding the certifications they have and the events they've reffed.
Manufacturer reps would have info regarding their position within the company they rep.
A parent would have information regarding how long they've been involved with the sport, perhaps relations with the users they are parent of.
Just as an example.
Edit 2:
**Player Table
id
user id
started date
stopped date
rank
**Ref Table
id
user id
started date
stopped date
is certified
certified by
verified
**Photographer / Videographer / News Reporter Table
id
user id
started date
stopped date
worked under name
website / channel link
about
verified
**Tournament / Big Game Rep Table
id
user id
started date
stopped date
position
tourney id
verified
**Store / Field / Manufacturer Rep Table
id
user id
started date
stopped date
position
store / field / man. id
verified
This is what I planned out so far. I'm still new to this so I could be doing it completely wrong. And it's only five groups. It was more until I condensed it some.
Although I find it weird having so many entities which are different from each other, but I will ignore this and get to the question.
It depends on the group criteria you need, in the case you described where each group has its own columns and information I guess your design is a good one, especially if you need the information in a readable form in the database. If you need all groups in a single table you will have to save the group relevant information in a kind of object, either a blob, XML string or any other form, but then you will lose the ability to filter on these criteria using the database.
In a relational Database I would do it using the design you described.
The design of your tables greatly depends on the requirements of your software.
E.g. your description of users led me in a wrong direction, I was at first thinking about a "normal" user of a software. Basically name, login-information and stuff like that. This I would never split over different tables as it really makes tasks like login, session handling, ... really complicated.
Another point which surprised me, was that you want to store the equipment in columns of those user's tables. Usually the relationship between a person and his equipment is not 1 to 1 and in most cases the amount of different equipment varies. Thus you usually have a relationship between users and their equipment (1:n). Thus you would design an equipment table and there refer to the owner's user id.
But after you have an idea of which data you have in your application and which relationships exist between your data, the design of the tables and so on is rather straitforward.
The good news is, that your data model and database design will develop over time. Try to start with a basic model, covering the majority of your use cases. Then slowly add more use cases / aspects.
As long as you are in the stage of planning and early implementation phasis, it is rather easy to change your database design.
In my program, I need to make an organization chart starting with individuals and grouping them under a manager, then group those managers under senior managers etc... How do I do this with regards to the database?? This is a many to one relationship - which I thought was illegal and impossible - and would be like starting with the child table - individuals - before creating its parent - manager.
If someone can help point me in the right direction to design my database I'd really appreciate it!!
----EDIT----
Here's a more detailed explanation of my problem:
Let's say a user of my program starts by entering in 35 individuals they'd like to use on some project they're going to work on. Now, there are several possible management positions that can be created and have employees/other (lower) managers assigned to those. The user doesn't HAVE TO create any particular position, but can pick and choose and assign however they like. The only constraints are there will always be a top manager - let's call him the President - and that he SHOULD (but doesn't HAVE TO) only assign 5-10 people to any given manager (president included). So in this example we are starting with 35 individuals and a President. Now we start grouping the 35 individuals into teams and assigning one of them as manager. Say the user decides to have two teams of 6, two teams of 9, and one team of 5 - each of these groups has one of its individual members assigned as manager of that team. So now we have 5 teams, each under its own manager, and those five managers would now be assigned to the President. The program would let this go but warn the user that the number of individuals under a manager in the last team is less than 5 (is only 4). So the user can now (or at ANYtime) go back and change the organization. So let's say he wants to fix this issue and changes up the teams. So he breaks up one of the two teams of 9 and assigns one individual to the team that was short a person. This makes a final count of 3 teams of 6 (5 individual members and one manager), one team of 9 (8 ind and 1 mngr), and one team of 8 (7 ind and 1 mngr) and all 5 team managers are assigned to the president.
Only in real life this can get broken down much further - nests with many more levels of management. How can I do this?
Is Joe Hopfgartner's answer below still valid? Can I just make a "role" column, even though the role would be assigned later (after the row is initially created)? Or changed at any time? Can this self-referencing foreign key be null? (as it would be in the case that no manager has been assigned yet) Or should I move the individuals to a separate "team" table after they've been assigned to a team and move the managers to a "manager" table once they've been assigned as a manager, then add a foreign key for the team table referencing the manager table?
Also, I am using MySQL, so does that fact that you cannot use self-referential ON UPDATE CASCADE or ON UPDATE SET NULL operations affect my particular case (since users will no doubt often be changing the assignments)?
Thank you so much for helping me with this!!!
if one individual can only have one manager, just introduce a "parent person" id field or put managers in a seperate table.
if not, create another table for a relation like "person_has_manager" that assigns a person to a manager.
you can also put managers and persons into the same table and introduce a "role" field, but this can be tricky when using foreign key constraints if you want to ensure that only manages can have persons assigned to them.
to solve this problem you can introduce a "person_is_manager" table that links person to their job as manager, and persons can be linked to be managed by that manager. this ould look like this:
persons
-> person_id (primary)
-> name
-> etc
managers
-> person_id (primary, linked to person_id in persons)
person_has_manager
-> person_id (primary)
-> manager_id (primary, linked to person_id in managers table)
It's a tree. You can use a single table with a parent_id field, to indicate which record is the parent to the current one.