Generate connections table in SQL - sql

I looked for this and did not find a solution that would apply to my scenario.
I'm building a database of game devs and I wish to generate a connections table:
I have the following:
Employee
(
name, date of birth, department they work at, task they do
)
Department
(
department name
)
Task
(
task name
)
and I need to generate a connections table that shows which department contributes to which task. I would do that by checking for each employee their department (only one) and task (also only one) and upon a match, the department contributes to that task.
That is the idea but I have to clue how to code it using Oracle

SELECT DISTINCT "department they work at", "task they do"
FROM Employee;

You should first work out an entity-relationship diagram, that lists the entities you use and with what attributes (and which primary keys), and the relations between those entities. Relationships can be: 1-to-1, 1-to-many and many-to-1, and many-to-many.
In the last case (M:N relation), the implementation in database tables requires an extra table to record such a M:N relationship.
The way to implement a 1:N relationship in a table is adding a foreign key in the child table to the primary key of the parent table.
EDIT: I see that you now supplied some details, and it is clear now that EMPLOYEE table is in fact the connection table, so you could simply query that table and show the DEPTID and TASKID (both the primary keys of their respective tables) to have a connection between departments and tasks. See the query in the other answer, and just add an ORDERBY on DEPTID, to show results in the order of DEPTID.

Related

Selecting those Affected by a 1:1 relationship

My teacher asked us to select from a 1:1 table called Employee; the supervisor and their role, and each employee they supervise with their role (employee is the primary key and those are the only 3 values in the table).
A 1:1 relationship are two tables with only one possible matching id.
It assumes that each supervisors only has one employee. so your query would look something like this.
SELECT Employee.Name, Employee.Role, supervise.Name, supervise.Role
FROM Employee
INNER JOIN supervise
ON Employee.EmployeeId = Supervise.EmployeeId
However, do note that in a real world context. This should have been a 1:N (One-To-Many) as each supervisors can have many employees.
Usually a 1:1 relationships are only used when you want to extended a table that you have no access or cannot modify. Otherwise, you would just add more columns to that original table. (or if you are working with a very old database system and you reach the max number of columns)

SQL database structure with two changing properties

Let's assume I am building the backend of a university management software.
I have a users table with the following columns:
id
name
birthday
last_english_grade
last_it_grade
profs table columns:
id
name
birthday
I'd like to have a third table with which I can determine all professors teaching a student.
So I'd like to assign multiple teachers to each student.
Those Professors may change any time.
New students may be added any time too.
What's the best way to achieve this?
The canonical way to do this would be to introduce a third junction table, which exists mainly to relate users to professors:
users_profs (
user_id,
prof_id,
PRIMARY KEY (user_id, prof_id)
)
The primary key of this junction table is the combination of a user and professor ID. Note that this table is fairly lean, and avoids the problem of repeating metadata for a given user or professor. Rather, user/professor information remains in your two original tables, and does not get repeated.

How to use FKs correctly in SQL Tables

Table Department:
DeptId
Name
Table Team
TeamId
*DeptId (FK)
Name
Table Employee
EmpId
*DeptId
*TeamId
I am making some updates on an old project, but I don't know why the old programmer designed those tables like this (like putting both DeptId and TeamId in the Employee table).
I find this useless because I can get the department from the Team table, and there's no need to put both FK IDs into the Employee table, TeamId is enough.
Is there any other reason that could force me to put both FKs in that table?
Thank you.
As the data model is written, an employee could be a member of a team that is not in his or her department.
That is probably possible, for instance, if the employee is temporarily on loan.
My bigger problem with the data model is that the relationships between employee and team and employee and department vary over time. So, I would have three tables for each entity. The only relationship in the tables would be between team and department (because that presumably does not change over time).
Then I would have two junction tables, one employeeDepartments and one employeeTeams that capture the changing relationships over time.

How to Delete all data from a table which contain self referencing foreign key

I have a table which has employee relationship defined within itself.
i.e.
EmpID Name SeniorId
-----------------------
1 A NULL
2 B 1
3 C 1
4 D 3
and so on...
Where Senior ID is a foreign key whose primary key table is same with refrence column EmpId
I want to clear all rows from this table without removing any constraint. How can i do this?
Deletion need to be performed like this
4, 3 , 2 , 1
How can I do this
EDIT:
Jhonny's Answer is working for me but which of the answers are more efficient.
I don't know if I am missing something, but maybe you can try this.
UPDATE employee SET SeniorID = NULL
DELETE FROM employee
If the table is very large (cardinality of millions), and there is no need to log the DELETE transactions, dropping the constraint and TRUNCATEing and recreating constraints is by far the most efficient way. Also, if there are foreign keys in other tables (and in this particular table design it would seem to be so), those rows will all have to be deleted first in all cases, as well.
Normalization says nothing about recursive/hierarchical/tree relationships, so I believe that is a red herring in your reply to DVK's suggestion to split this into its own table - it certainly is viable to make a vertical partition of this table already and also to consider whether you can take advantage of that to get any of the other benefits I list below. As DVK alludes to, in this particular design, I have often seen a separate link table to record self-relationships and other kinds of relationships. This has numerous benefits:
have many to many up AND down instead of many-to-one (uncommon, but potentially useful)
track different types of direct relationships - manager, mentor, assistant, payroll approver, expense approver, technical report-to - with rows in the relationship and relationship type tables instead of new columns in the employee table
track changing hierarchies in a temporally consistent way (including terminated employee hierarchy history) by including active indicators and effective dates on the relationship rows - this is only fully possible when normalizing the relationship into its own table
no NULLs in the SeniorID (actually on either ID) - this is a distinct advantage in avoiding bad logic, but NULLs will usually appear in views when you have to left join to the relationship table anyway
a better dedicated indexing strategy - as opposed to adding SeniorID to selected indexes you already have on Employee (especially as the number of relationship types grows)
And of course, the more information you relate to this relationship, the more strongly is indicated that the relationship itself merits a table (i.e. it is a "relation" in the true sense of the word as used in relational databases - related data is stored in a relation or table - related to a primary key), and thus a normal form for relationships might strongly indicate that the relationship table be created instead of a simple foreign key relationship in the employee table.
Benefits also include its straightforward delete scenario:
DELETE FROM EmployeeRelationships;
DELETE FROM Employee;
You'll note a striking equivalence to the accepted answer here on SO, since, in your case, employees with no senior relationship have a NULL - so in that answer the poster set all to NULL first to eliminate relationships and then remove the employees.
There is a possibly appropriate usage of TRUNCATE depending upon constraints (EmpployeeRelationships is typically able to be TRUNCATEd since its primary key is usually a composite and not a foreign key in any other table).
Try this
DELETE FROM employee;
Inside a loop, run a command that deletes all rows with an unreferenced EmpID until there are zero rows left. There are a variety of ways to write that inner DELETE command:
DELETE FROM employee WHERE EmpID NOT IN (SELECT SeniorID FROM employee)
DELETE FROM employee e1 WHERE NOT EXISTS
(SELECT * FROM employee e2 WHERE e2.SeniorID = e.EmpID
and probably a third one using a JOIN, but I'm not familiar with the SQL Server syntax for that.
One solution is to normalize this by splitting out "senior" relationship into a separate table. For the sake of generality, make that second table "empID1|empID2|relationship_type".
Barring that, you need to do this in a loop. One way is to do it:
declare #count int
select #count=count(1) from table
while (#count > 0)
BEGIN
delete employee WHERE NOT EXISTS
(select 1 from employee 'e_senior'
where employee.EmpID=e_senior.SeniorID)
select #count=count(1) from table
END

Can a many-to-many join table have more than two columns?

I have some tables that benefit from many-to-many tables. For example the team table.
Team member can hold more than one 'position' in the team, all the positions are listed in the position db table. The previous positions held are also stored for this I have a separate table, so I have
member table (containing team details)
positions table (containing positions)
member_to_positions table (id of member and id of position)
member_to_previous_positions (id of member and id of position)
Simple, however the crux comes now that a team member can belong to many teams aghhh.
I already have a team_to_member look-up table.
Now the problem comes how do I tie a position to a team? A member may have been team leader on one team, and is currently team radio man and press officer on a different team. How do I just pull the info per member to show his current position, but also his past history including past teams.
Do I need to add a position_to team table and somehow cross reference that, or can I add the team to the member to positions table?
It's all very confusing, this normalization.
Yes, a many-to-many junction table can have additional attributes (columns).
For example, if there's a table called PassengerFlight table that's keyed by PassengerID and FlightID, there could be a third column showing the status of the given passenger on the given flight. Two different statuses might be "confirmed" and "wait listed", each of them coded somehow.
In addition, there can be ternary relationships, relationships that involve three entities and not just two. These tables are going to have three foreign keys that taken together are the primary key for the relationship table.
It's perfectly legitimate to have a TeamPositionMember table, with the columns
Team_Id
Position_Code
Member_Id
Start_Date
End_Date NULLABLE
And and a surrogate ID column for Primary Key if you want; otherwise it's a 3-field composite Primary Key. (You'll want a uniqueness constraint on this anyway.)
With this arrangement, you can have a team with any set of positions. A team can have zero or more persons per position. A person can fill zero or more positions for zero or more teams.
EDIT:
If you want dates, just revise as shown above, and add Start_Date to the PK to allow the same person to hold the same position at different times.
My first thought:
Give your many-to-many teams/members table an ID column. Every team-to-member relationship now has an ID.
Then create a many-to-many linking positions to team-member relationships.
This way, teams can have multiple members, members can have multiple teams, and members can have multiple positions on a per-team basis.
Now everything is nice and DRY, and all the linking up seems to work. Does that sound right to anyone else?
Sounds like you need a many-to-many positions to teams table now.
Your team_to_member table can indeed have an extra column position_id to describe (or in this case point to) the position the member has within that team.
Get rid of member_to_previous_position table. Just use member_to_positions and have these columns:
MemberToPositionID (autoincrement OK only)
MemberID
PositionID
StartDate
EndDate
Then to find current positions, you do:
select *
from member_to_positions
where EndDate is null