MySQL Change column value to the least value in its category - mysql

Assuming only one school can be identified in a specific town, you are required to move students from duplicated schools to originally created schools. We also assume that lowest school id implies the first schools to be created in
the database, hence original schools.
I want to achieve this simply by changing the school ids for duplicate school+town to the smallest school id (the original) in that category. This will take care of the student records table that is linked to this one via foreign key (school id).
How would I go about doing this on the table attached? I'm thinking along the lines of SELECT MIN, CASE STATEMENTS as well as GROUP BY and COUNT() but I'm at a loss on how to combine these. Anyone have an idea/code on how I would achieve the requirement above?

I'd assume that the school id is a unique identifier (key). Therefore you can't just update it in the schools table. You'd rather need to update the school_id column in the students table to point to the original school's id.
If this is the case you can do something along the lines of
-- get all students and their current school info for update
UPDATE students st JOIN schools sc
ON st.school_id = sc.id JOIN (
-- get ids of original schools
SELECT town, name, MIN(id) id
FROM schools
GROUP BY town, name
) q -- join students with a list original schools ids
ON sc.town = q.town AND sc.name = q.name
-- change the school id to the original one
SET st.school_id = q.id
-- but only for students that were associated with non-original schools
WHERE st.school_id <> q.id
Here is dbfiddle demo

Related

mySQL: how to go along 3 different tables, referring to different column in each table but using primary keys

I'm trying to find out which schools had students that did not complete their exams in 2018. So I've got 3 tables set up being: ExamInfo, ExamEntry and Students. I'm going to try use the ExamInfo table to get information from the Students table though, I obviously only want the student information that did not complete their exam in 2018. Note: I'm looking for students that attended, though did not complete the exam, with this particular exam you can look at completed exam as passed exam.
Within ExamInfo I have the columns:
ExamInfo_Date --when exam took place, using to get year() condition
ExamInfo_ExamNo --unique student exam ID used to connect with other tables
ExamInfo_Completed --1 if completed, 0 if not.
...
Within ExamEntry I have the related columns:
ExamEntry_ExamNo --connected to ExamInfo table
ExamEntry_StudentId --unique studentId used to connect to Students table
ExamEntry_Date -- this is same as ExamInfo_Date if any relevance.
...
Within Students I have following columns:
Students_Id --this is related to ExamEntry_StudentId, PRIMARY KEY
Students_School --this is the school of which I wish to be my output.
...
I want my output to simply be a list of all schools that had students that did not complete their exams in 2018. Though my issue is with getting from the ExamInfo table, to finding the schools of which students did not complete their exam.
So far I've:
SELECT a.Students_School, YEAR(l.ExamInfo_Date), l.ExamInfo_Completed
FROM ExamInfo l ??JOIN?? Students a
WHERE YEAR(l.ExamInfo_Date) = 2018
AND l.ExamInfo_Completed = 0
;
I'm not even sure if going through the ExamEntry table is necessary. I'm sure I'm meant to use a join, though unsure of how to appropriately use it. Also, with my 3 different SELECT columns, I only wish for Students_School column to be output:
Students_School
---------------
Applederry
Barnet Boys
...
Clearly, you need a JOIN -- two in fact. Your table has exams, students, and a junction/association table that represents the many-to-many relationship between these entities.
So, I would expect the FROM clause to look like:
FROM ExamInfo e JOIN
ExamEntry ee
ON ee.ExamEntry_ExamNo = e.ExamNo JOIN
Students s
ON ee.ExamEntry_StudentId = s.Students_Id

MySQL Attendance System , Problems with joining tables, duplicate id's for 1 primary key

Ok So I am creating a Attendance System for a College and I am having trouble doing the tables in MySQL
The Problem I'm having is Grouping a group of students together for one class. So in MySQL
TABLE NAME: CourseGroup: courseGroup_id , student_id(FK), course_id(FK)
I want a number of students belonging to one class, this in hindsight will enable a teacher to undertake a register for that class group
In MySQL I have set the 'courseGroup_id as a unique field, however when I try to link 'courseGroup_id' in the Attendance table it only enables me to select 'student_id' and 'course_id'
Is it possible to select the courseGroup_id and display students for one class
My Attendance table looks like this:
Attendance: week_number, day, time, courseGroup_id, present
I want to be able to view all the students that belong to one class
I’m a bit lost with your terminology, you speak of “class id” but don’t reefer to that in your question – instead you use “course”.
I think the best option you can do here is create another table enabling a many to many relationship as many students can be registered to one or many courses. This type of table will enable a mapping between students and courses.
For example, if you create the mapping table “student_courses” with
student_id INT
course_id INT
You can then select students by course (joining the student table)
SELECT * from student_courses sc
INNER JOIN students s
ON s.student_id = sc.srudent_id
WHERE sc.course_id = ?CourseId
You can also reverse it and show the courses by for an individual course:
SELECT * from student_courses sc
INNER JOIN courses cs
ON cs.courset _id = sc.course_id
WHERE sc.student_id = ?StudentId
It is also worth pointing out that there should be two index on the student_courses, indexing both student_id and course_id for performance reasons.

Transition (many to many join) tables in MySQL; allowing for duplicate entries to link 1 column to multiple other columns in different table

Ok, so I am going to try and be specific as possible but my MySQL skills are pretty weak. So here is the situation:
I have 2 tables: Donor and Students. A donor can be linked to as many students as they want and each student can be linked to as many donors as donors want to "claim" them. So if I have Sally, a student, she can have Jim, a donor, and Jeff, a donor, be linked to her. So, I have all my students in one table and all my donors in another table. I need to put them together show the students name, id and the id of all the donors that the student is linked to.
Currently my tables are: Donor with DonorID, FirstName, LastName, DonorType, StreetAddress, etc. Then Students with: StudentID, FirstName, LastName and DonorID. However, that only allows me to link a student with one donor. So, I was thinking I need to make a transition table that would allow me to show the StudentID, FirstName(of student), LastName(of student), and the DonorID that "claims" that student and allow for me to duplicate StudentID and put a different DonorID in the 2nd, 3rd, 4th, so on and so on entries of the same student.
So, I guess my question is how do transition tables work in MySQL; I believe I am going to need to work with the JOIN function and join the two tables together but after reading about that on tizag.com I am even more confused. I have worked with Access where when you create a transition table you can pull the PK from each table and create a composite key using the two keys from the other tables but I am not quite sure how to do that in MySQL; does it work essentially the same and I should be pulling the PK from each table and linking them together in the 3rd, transition, table?
Marvin's right.
You need three tables to pull this off.
Donor
DonorID
FirstName
LastName
DonorType
StreetAddress
etc.
Student
StudentID
FirstName
LastName
etc.
Then you need Student_Donor. This is often called a join table, and implements the many-to-many relationship.
StudentID (PK) (FK to Student)
DonorID (PK) (FK to Donor)
DonorOrdinal
If StudentID = 5 has four donors with ID = 6,7,11,15, then you'l have these rows
StudentId DonorId DonorOrdinal
5 6 1
5 7 2
5 11 3
5 15 4
The DonorOrdinal column allows you to specify a student's primary donor and secondary donors. I can't tell from your question how important that is, but it's helpful to be able to order these things. Remember this: formally speaking, a SQL SELECT query returns rows in an unpredictable order unless you also specify ORDER BY.
If you want to display your students and their donors, you'll need this query:
SELECT s.StudentID, s.FirstName, s.LastName,
sd.DonorOrdinal,
d.DonorType, d.DonorID, d.FirstName, d.LastName
FROM student s
LEFT JOIN student_donor sd ON s.StudentID = sd.StudentID
LEFT JOIN donor d ON sd.DonorID = d.DonorID
ORDER BY s.StudentID, sd.DonorOrdinal, d.DonorID
This will show you all students (whether having donors or not per LEFT JOIN) in order of ID, then their donors in order of DonorOrdinal.
Yes, pretty much. What you are talking about is a Many to Many relationship. Your donor table should not include a reference to the student table (and vice versa). You'll need a new table (what you are calling a transition table) that contains the DonorId and StudentId. This can comprise your primary key or you can use another column for the primary key that is an auto_increment.

in MySQL, how to use information from one table to update another table

I have two tables: teams, and persons.
table teams have three columns, id, name, leader
table persons have these columns: hash, team_id
teams.leader is a MD5 hash that must match persons.hash in order to determine which person is leader of a given team.
I need to run a query on MySQL that does the following:
1) Retrieve all the leaders of a team, and the team id:
SELECT `id`,`leader` FROM `teams`;
2) Use such information to update team_id on table persons
This is my current Query:
SELECT id FROM teams INNER JOIN persons ON teams.leader = persons.hash
but I haven't been able to come up with a solution that allows me update column team_id with the corresponding leader.
I've been thinking probably using cursors, but not sure about it.
Any ideas?
You can use the multiple table UPDATE syntax to join the tables:
UPDATE teams JOIN persons ON teams.leader = persons.hash
SET persons.team_id = teams.id

Is this possible w/ SQL?

I'm working with a SQL database for a Skills Matrix application and I need a query to return a list of employees that are qualified for a given position. Here's a brief overview of the relevant relationships:
Employee has many skills through
qualifications
Position has many
skills through requirements
Is there a efficient way to return a list of employees that have the qualifications to meet a certain position's requirements?
EDIT
employees
- id
- name
positions
- id
- title
skills
- id
- name
requirements
- position_id
- skill_id
qualifications
- employee_id
- skill_id
SELECT *
FROM employees e
WHERE NOT EXISTS (
SELECT *
FROM requirements r
WHERE r.position_id = 1234
AND NOT EXISTS (
SELECT *
FROM qualifications q
WHERE q.skill_id = r.skill_id
AND q.employee_id = e.employee_id
)
)
It will find all employees such that there are no requirement that is not filled by the employee's qualifications.
The use of nested NOT EXISTS is even mentioned in the MySQL Reference Maual
Sure, it's possible. I count seven tables there: Employee, Qualifation, EmployeeQualifications, Position, Requirement, PositionRequirements, and RequirementQualifications. If your Qualifications and Requirements will always be 1:1 (ie, they are the same thing), you can do it more simply (5 tables) like this: Employee, Position, Skill, EmployeeSkills, PositionSkills.
Once you have the tables defined, the trick to building the query is to first look for any positions for which an employee is not qualified, and then do an exclusion join with that result set back to the position table to get your results.
Yes, to achieve what you want you need, given a Position to return only those Employees, that have qualifications that collectively include all the skills the Position requires. If you retrieve these Employees, this list it will represent the list of the customers you are after.
Update
Since I do not have any experience with mysql, my reply only deals with sql server.
Try something like this:
select
qualifications.employee_id
from
qualifications
join
requirements
on
requirements.skill_id = qualifications.skill_id
where
requirements.position_id = 1234
group by
qualifications.employee_id
having
count(qualifications.skill_id) = (select count(distinct skill_id) from requirements where requirements.position_id = 1234)
Create an index on each of
employees.id
qualifications.employee_id
qualifications.skill_id
requirements.skill_id
requirements.position_id