SQL First Normal Form (1NF) vs Serialisation - mysql

Lets say I have a football team table, where player names are tied to positions:
teamId: 1
goalkeeper: 'Marc'
position1: 'John'
position2: 'Erik'
...
But now I also want one attribute that represents the players NOT taking into account positions. I would create a new attribute teamString serialising all players sorted alphabetically (this will ensure that different Teams with same players will have the same teamString attribute):
teamString: Eric-John-Mark[...]
Now I can filter Teams with same players even if they play in different positions.
Will this new attribute teamString be against 1NF principle?
Thanks in advance

Your teamString attribute would be a violation of the 1NF as your teamString property would contain multiple values. And it would reference values existing in non-key attributes of the same entity (maybe a 3NF violation but I'm not sure about it).
The issue here is that you treated specific positions in a team as attributes of the team and not as a relation.
I'd make a relation between team and player:
team (1, n) - (0, n) player
A team may have one to many players.
A player may play for zero to many teams.
As both max cardinalities are to n you'd get a Many To Many relation which implies a join table with foreign keys from both sides (the team id + player id). In this table you can add a column for the position type.
This means you should get rid of the position columns (goalkeeper, position1, ...) in the team table.
The position table could look like:
team_id
player_id
type
1
12
goal_keeper
1
15
position1
2
12
position_2
Then the application could be responsible for checking that a team has only a limited number of players for a specific position. But for modeling you should stick to the 0, 1 & "n" values that you use in cardinalities.

Related

Database Model - Tournaments for eSports

I'm quite new to Database Modelling and I'm struggling a bit with my Tournament Module Structure.
The following is what I managed to come up with so far:
Click here
Overview:
(TABLE) Seasons - All tournaments/leagues/ladders fall under it. Plain & simple.
(TABLE) Tournaments:
Related to the 'parent'->seasons via season_id
Tournament Format - allow 1vs1 or team-based participation.
Tournament Type - as the name hints: tournament, league, ladder
The rest in Tournaments is pretty self-explanatory so I'll skip ahead.
(SUB-TABLE)Tournament Entries - 1 Table Row per Every Participating Player, AND Team (If format is Team-based). It's moderated with column is_team (= 0, means Player Entry).
(SUB-TABLE)Tournament Matches - connected to Tournaments via entry_id->tournament_id (Possible?). Columns team A & B are populated based on entry_id->is_team (When 0 assigns entry_id->player_id otherwise entry_id->team_id).
(TABLE) Player Statistics - 1 Table Row per Every Team PLAYED FOR during Tournament => meanning, a Player can:
Transfer teams in the same tournament.
View previous recorded stats during the time he played for them.
I'm struggling with structuring current stage/phase of the tournament, play-offs, groups, single/double elimination, loser bracket and round-robin. In addition, how to track 'Best of' type of matches. How do I track that and create matches (new and based on previous results)?
Also, are my created relations & indexes correct and efficient?
NOTE: don't pay attention to the field types, it will be re-organized.
Thanks in advance!

Issues with Schema Design

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.

MySQL: non-subordinative self relationship

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.

Alternative solution for comma separated values when the column count is unknown | MySQL

I have a requirement to design a table which almost looks like a 3 dimensional requirement.
For example,
There are "infinite" varieties of Dinosaurs.
All the Dinosaurs will have some common set of features (name, years since existence on earth, weight, family name, etc.,).
There will be some specific features which are sometimes unrelated to each variety. Each such feature is identified with a "name"="value" pair. The "name" is something like the name of a feature (like may be horns on head, the voice frequency etc) and the "value" could be the value of the feature (like 3 horns on the head, some 10hz voice frequency etc.,).
As per the requirement we can create a table X with common features like columns referring to cid, name, years since existence, weight etc.,. And there there could be another table Y with just columns (uid, name, value) where cid could be bound used for the uid.
But the fact that, the number of rows in X would be enormous (trillion+, we might not have so many dinosaur families, but that is just an example). Similarly, the name=value would be several hundreds per entry in table X. This would increase the number of rows in table Y.
Since, the feature "name" is also "infinite", we cannot create a table with fixed number of columns, like column per feature unfortunately because that would be like dynamic columns.
One idea would be to have two more columns in table X, where one column can consist of all the features ("name") as comma separated and the other column can consist of all the "values" in comma separated. But I know this is a very bad design.
Could there be any better solutions for this requirement?
Have a look at below example. You specify the species of dinosaurs in dinosaur_type, the individual dinosaur go in table dinosaur and are linked to a species/type and then in dinosaur_feature you can add rows for each individual dinosaur to add any kind of (infinite) possible feature for a dinosaur..
Table `dinosaur`:
id
dinosaur_type_id (fk)
name
years since existence on earth
weight
family name
Table `dinosaur_type`:
id
name
Table `dinosaur_feature`:
dinosaur_id (fk)
feature_name
feature_value

Resolve many-to-one, child before parent table problem

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.