How do I delete duplicate values with group by - mysql

Example database :
ID StudentName StudentClass
1 John A
2 John B
3 Peter A
4 John A
5 John B
I want the result should be
ID StudentName StudentClass
1 John A
2 John B
3 Peter A
Statment
DELETE FROM Student
WHERE ID NOT IN (SELECT *
FROM (SELECT MIN(n.ID)
FROM Student n
GROUP BY n.StudentName) x)
How do I keep John name on class A & B?

DELETE a FROM Student a
LEFT JOIN
(
SELECT MIN(ID) AS minid
FROM Student
GROUP BY StudentName, StudentClass
) b ON a.id = b.minid
WHERE
b.minid IS NULL

A better method to disallow even insertion of such duplicates would be multi-column unique index(it will optimize your searches too). Here is how:
ALTER TABLE `Student`
ADD UNIQUE INDEX `idx` (`StudentName`, `StudentClass`)

You should be able to join Students against itself, with a JOIN predicate that ensures the JOIN matches duplicate students, and delete the join'd row:
DELETE
duplicate_students.*
FROM Students JOIN Students as duplicate_students
ON Students.StudentName = duplicate_students.StudentName
AND Students.StudentClass = duplicate_students.StudentClass
AND duplicate_students.ID > Students.ID
NOTE: Please back up your data first; I take no responsibility for lost data :-) This is a conceptual idea and has not been tested.

This should work:
DELETE S FROM Student S
INNER JOIN(
SELECT MIN(ID) AS ID,StudentName,StudentClass FROM Student
GROUP BY StudentName,StudentClass
) S2 ON S.ID != S2.ID AND S.StudentName = S2.StudentName AND S.StudentClass = S2.StudentClass
Its basically selecting the minimum ID out of all the duplicate records in sub query. Then we simply delete everything that matches that Class and Name, But we don't match the Minimum Id, so at end of day, we are keeping (presumably) 1st record out of duplicates and eradicating rest.

Related

Return the Inverse of Tuples from an INNER JOIN Query

I am trying to get the remaining tuples from a query. In this case, course_id 3 and 4 from courses because the user admin# has NOT taken these (they've only taken 1 and 2). The tables are already joined nicely and queries are working when I try a LEFT JOIN ...
select course_name from courses LEFT OUTER JOIN users_courses ON users_courses.user_course_id = courses.course_id where users_courses.user_email = "admin#---.com";
But this returns the courses 1 and 2, not 3 and 4
you could do another thing by getting all of the courses that is not exists in the courses list for this user like this
select course_name from courses where course_id not in (select user_course_id from users_courses where user_email = 'admin#....')
update
forget to add the column name course_id
Ah! I misunderstood what you were after. Joseph's method will work, but, as a rule, you should try to avoid "in(select...".
To knock-out the courses the admin has taken, just add a null condition:
select course_name from courses LEFT OUTER JOIN users_courses
ON users_courses.user_course_id = courses.course_id
and users_courses.user_email = "admin#---.com"
where users_courses.course_id is null;

SQL inner join wrong output from two tables

Students Table:
ID | Family_ID | Student_name | F_name
Families Table:
ID | F_name | Contact_No
i want to get all records from students where family_id is repeating.(basically i want to know students Brothers/Sisters records if there is any in student table.
i tried it this way but got wrong output;
SELECT students.*
FROM students
INNER JOIN families
ON families.id = students.family_id
ORDER BY families.id ASC
my query result in image: as you can see some ids are showing once others are more then once, but i think all should appear more then once.
If you want to see only relevant people you don't need to link it to the families table. You can group the student with family_id. Here is your query :
SELECT *
FROM Student
WHERE family_id IN (SELECT family_id
FROM students
GROUP BY family_id
HAVING COUNT(1)>1)
ORDER BY family_id
You could try using a join on subquery for the family_id that have more that one rows in students
SELECT students.*
FROM students
inner join (
select students.family_id
FROM students
group by students.family_id
having count(*)>1
) t on t. family_id = students.family_id

SQL: Selecting existence of an entry in another table

I am trying to select whether or not an entry exists in another table. Here's a simple example:
Two tables:
Student
ID Major
1 CS
2 CS
3 CS
4 CS
Student_Teacher
SID TID
1 A
1 B
1 C
3 B
3 D
The first table has a list of student IDs (key = Student ID)
The 2nd table has a list of student -> teachers (key = Student ID, Teacher ID combination).
I would like to select ALL students (1,2,3,4; one in each row) and a flag for whether or not they have a teacher.
SELECTED:
ID Flag
1 1
2 0
3 1
4 0
I know this is possible to do using group by:
select Student.ID, count(Student_Teacher.TID)
from Student left join Student_Teacher
group by Student.ID
Is there a simpler way?
You can try joining to a derived table that contains the distinct student id values of the second table:
SELECT ID, IF(ST.SID IS NOT NULL, 1, 0) AS FLAG
FROM Student AS S
LEFT JOIN (
SELECT DISTINCT SID
FROM Student_Teacher
) AS ST ON S.ID = ST.SID

how to get Intersection of two query in mysql

I have a table that has two column with two foreign key from two different table.
this is my relation table:
I want to select those student who can speak both language with id 3 and 4.
How can i wrote a query to give me for e.x 12 , 14
You can give it a try:
SELECT
student_id,
COUNT(*) total
FROM your_table
WHERE language_id IN (3,4)
GROUP BY student_id
HAVING COUNT(*) = 2;
Only IN doesn't ensure that a student is involved both in language id 3 & 4.
You need to use GROUP BY student_id HAVING COUNT(*) = 2 in order to ensure those student_ids to be in the result who were involved both in language id 3 & 4
Another solution would be using INNER JOIN. But it doesn't scale.
SELECT
A.student_id
FROM your_table A
INNER JOIN your_table B ON A.student_id = B.student_id
AND A.language_id = 3 AND B.language_id = 4
Assume your relation is named "my-relation":
SELECT R1.student_Id FROM my-Relation R1 join my-Relation R2 on R1.student_id = R2.student_id where R1.language_Id = '3' and R2.language_id = '4'

Write a query to find the students with the same first name AND last name?

So here is what I have tried:
SELECT A.STUDENT_ID
FROM STUDENT A, STUDENT B
WHERE A.FNAME=B.FNAME
AND A.LNAME=B.LNAME
AND A.STUDENT_ID!=B.STUDENT_ID;
Here is the STUDENT table columns:
STUDENT_ID primary key
FNAME
LNAME
It seems to work. But according to the practice exam, it is worth 15 points so I am not sure if it is totally right. What if there more that two students have the same fname and lname? How would I write it or would this work for that too?
To avoid the Cartesian product (which is what you get with those multiple FROM clauses) and the duplicate rows that would create, I'd use an EXISTS clause
SELECT a.STUDENT_ID, a.FNAME, a.LNAME
FROM STUDENT a WHERE EXISTS (
SELECT 1 FROM STUDENT b
WHERE a.FNAME = b.FNAME
AND a.LNAME = b.LNAME
AND a.STUDENT_ID <> b.STUDENT_ID
);
http://sqlfiddle.com/#!9/75fd6/3
You would also benefit greatly by having an index on both FNAME and LNAME but I doubt that's going to be relevant to your practice exam.
What you have will technically work. However, the number of rows returned per matched student will equal n - 1, where n is the number of students who have the same first and last name as the matched student.
To address this, use a DISTINCT clause in your query.
SELECT DISTINCT A.STUDENT_ID
FROM STUDENT A, STUDENT B
WHERE A.FNAME=B.FNAME
AND A.LNAME=B.LNAME
AND A.STUDENT_ID!=B.STUDENT_ID;