removing duplicates from a table which has association with another table - mysql

Student
_______________________
SudentId Name
101 Peter
103 John
112 James
116 Peter
117 Peter
SudentId_Subject
_______________________
SudentId Subject
101 Physics
103 Chemistry
112 Mathematics
116 Physics
117 Commerce
To find duplicate students, I tried the query
select * from Student group by Name having count(*)>1, got
SudentId Name
_______________________
101 Peter
116 Peter
117 Peter
Actually I need to filter students with the same subject. ie,
101 Peter
116 Peter
are duplicates (same subject) but not 117 Peter
How can I write query for this?

I may have over complicated things, but couldn't think of an easier way :
SELECT ss.student_id,ss.name
FROM student ss
JOIN studentid_subject tt
ON(ss.student_id = tt.student_id)
JOIN(SELECT t.name,s.department
FROM student t
JOIN studentid_subject s
ON(t.student_id = s.student_id)
GROUP BY t.name,s.department
HAVING COUNT(*) > 1) p
ON(ss.name = p.name and tt.department = p.department)

select * from student left join SudentId_Subject on Student.SudentId = SudentId_Subject.DepId where Student.SudentId=SudentId_Subject.DepId

Related

SQL query for duplicate rows based on 2 columns

I have 3 tables movie, rating and reviewer
movie has 4 columns movieID, title, year, director
rating has 4 columns reviewerID, movieID, stars, ratingDate
reviewer has 2 columns reviewerID, name
How do I query reviewer who rated the same movie more than 1 time and gave it higher rating on the second review.
This is my attempt at query to find rows with duplicate values in 2 columns (meaning the movie has been rated by 1 reviewer more than once), and then somehow I need to query reviewer who gave higher stars on second review.
SELECT reviewer.name, movie.title, rating.stars, rating.ratingDate
FROM rating
INNER JOIN reviewer ON reviewer.rID = rating.rID
INNER JOIN movie ON movie.mID = rating.mID
WHERE rating.rID IN (SELECT rating.rID FROM rating GROUP BY rating.rID, rating.mID HAVING COUNT(*) > 1)
ORDER BY reviewer.name, rating.ratingDate;
movie table
movieID
Title
Year
Director
101
Gone with the Wind
1939
Victor Fleming
102
Star Wars
1977
George Lucas
103
The Sound of Music
1965
Robert Wise
104
E.T.
1982
Steven Spielberg
105
Titanic
1997
James Cameron
106
Snow White
1937
null
107
Avatar
2009
James Cameron
108
Raiders of the Lost Ark
1981
Steven Spielberg
rating table
reviewerID
movie ID
Stars
ratingDate
201
101
2
2011-01-22
201
101
4
2011-01-27
202
106
4
null
203
103
2
2011-01-20
203
108
4
2011-01-12
203
108
2
2011-01-30
204
101
3
2011-01-09
205
103
3
2011-01-27
205
104
2
2011-01-22
205
108
4
null
206
107
3
2011-01-15
206
106
5
2011-01-19
207
107
5
2011-01-20
208
104
3
2011-01-02
reviewer table
reviewerID
Name
201
Sarah Martinez
202
Daniel Lewis
203
Brittany Harris
204
Mike Anderson
205
Chris Jackson
206
Elizabeth Thomas
207
James Cameron
208
Ashley White
Expected result
Reviewer
Title
Sarah Martinez
Gone with the Wind
EDIT: I am using MySQL version 8.0.29
Use:
select re.Name,mo.Title
FROM (
select reviewerID,movieID,ratingDate,Stars
from rating r
where exists (select 1
from rating r1
where r1.reviewerID=r.reviewerID
and r.movieID=r1.movieID
and r.ratingDate>r1.ratingDate
and r.Stars>r1.Stars
)) as t1
inner join movie mo on t1.movieID=mo.movieID
inner join reviewer re on t1.reviewerID=re.reviewerID
https://dbfiddle.uk/?rdbms=mysql_8.0&fiddle=0c5d850ee3393b054d9af4c4ac241d96
The key part is the EXISTS statement
where exists (select 1
from rating r1
where r1.reviewerID=r.reviewerID
and r.movieID=r1.movieID
and r.ratingDate>r1.ratingDate
and r.Stars>r1.Stars
which will return only the results on which you have the same user more than one movie, the rating Stars are bigger than the previos one based on the ratingDate
we don't need to use where in with rating and join with rating
You can try to use lead window function to get the next start each reviewerID and movieID which represent duplicate rating (order by ratingDate)
then compare with your logic to find a newer start greater than older start.
SELECT DISTINCT r.Name,m.Title
FROM (
SELECT reviewerID,
movieID,
Stars,
LEAD(Stars) OVER(PARTITION BY reviewerID, movieID ORDER BY ratingDate) n_start
FROM rating
) t1
INNER JOIN movie m ON t1.movieID = m.movieID
INNER JOIN reviewer r ON r.reviewerID = t1.reviewerID
WHERE Stars < t1.n_start
This sample data sqlfiddle provide by #ErgestBasha

MySQL three table join with sum

I have three tables
Student
studenid stuname
101 john
102 aron
103 mary
104 lucy
Subject
studenid subjid subjname
101 1 maths
102 2 science
103 3 computer
104 4 english
Marks
subjid mark
1 50
2 40
3 55
4 60
1 40
2 55
3 60
I want output like this where studenid (sum of mark as total)
studenid stuname mark
101 john 90
102 aron 95
103 mary 115
104 lucy 60
Thank you in advance for yout help, i want output like this even join query or subquery which is best for timing
This just requires a straight left join across all tables, with an aggregation by student.
SELECT
st.studenid,
st.stuname,
COALESCE(SUM(m.mark), 0) AS mark
FROM Student st
LEFT JOIN Subject su
ON st.studenid = su.studenid
LEFT JOIN Marks m
ON su.subjid = m.subjid
GROUP BY
st.studenid,
st.stuname;
Demo
Note that if studenid be a primary key in the Student table, then strictly we would only need to aggregate by this column alone.

Join a report table based on three relational tables

Below are the given tables:
`student` `subject`
------------------- -------------------
id name id subject
------------------- -------------------
1 Alice 1 Maths
2 Bob 2 Science
3 Eve 3 Economics
------------------- -------------------
`marks`
-----------------------------------------------------
id student_id subject_id marks
-----------------------------------------------------
1 1 1 30
2 1 2 40
3 2 3 50
4 3 1 60
5 3 2 70
-----------------------------------------------------
I need an output which should look like below:
`o/p`
----------------------------------------------
name subject marks
----------------------------------------------
Alice Maths 30
Alice Science 10
Alice Economics NULL
Bob Maths NULL
Bob Science NULL
Bob Economics 50
Eve Maths 60
Eve Science 70
Eve Economics NULL
----------------------------------------------
Please note that I am targeting MySQL 5.6.x syntax and I have created a SQL fiddle of above here to ease access to the question.
Here you go
select
st.name,
su.subject,
m.marks
from student as st
cross join subject as su
left join marks as m on m.student_id=st.id and m.subject_id=su.id
order by st.name, su.subject
SELECT student.name,
subject.subject,
marks.marks
FROM student
JOIN subject ON student.id = subject.id
JOIN marks ON student.id = marks.id
ORDER BY student.name,
subject.subject

Query to display the only the most recent message of each thread

Environment PHP 5.3.5 phpMyAdmin 3.3.9
Here's an link of the issue in sqlfiddle
Trying to create a query which filters through a user's message activity. The activity will display the most recent threads based upon message recently added. So I have to consider if the user is the recipient or sender.
I have a query structured but I am having great difficulty on grouping the threads. When I group the threads, the order of the most recent activity is lost.
Here is the query and results which captures the correct order of the last 10 messages but there are duplicate thread_ids. I want to only display the most recent thread based upon the message sent date.
SQL query:
SELECT m.date_sent, m.thread_id, m.message_id, m.sender_id,
upub2.firstname as sender_name, mr.recipient_id,
upub1.firstname as recipient_name
FROM message AS m
JOIN message_recipient AS mr ON mr.message_id = m.message_id
JOIN user_public_info AS upub1 ON upub1.user_public_info_id = mr.recipient_id
join user_public_info AS upub2 ON upub2.user_public_info_id = m.sender_id
WHERE ((m.senderDelete IS NULL OR m.senderDelete = 0) AND m.sender_id = 2 ) OR
((mr.is_delete IS NULL OR mr.is_delete = 0 ) AND mr.recipient_id = 2)
ORDER BY m.message_id;
Results:
date_sent thread_id message_id sender_id sender_name recipient_id recipient_name
2013-10-09 14:31:50 106 113 1 John 2 Mark
2013-10-09 14:30:50 107 112 2 Mark 1 John
2013-10-09 14:30:31 106 111 2 Mark 1 John
2013-10-09 09:49:58 112 110 1 John 2 Mark
2013-10-09 09:20:24 108 106 1 John 2 Mark
2013-10-07 15:46:15 107 105 1 John 2 Mark
2013-10-07 14:40:25 103 104 1 John 2 Mark
2013-10-07 14:39:37 103 103 1 John 2 Mark
2013-10-07 14:36:34 107 102 2 Mark 1 John
2013-10-07 14:36:07 106 101 2 Mark 1 John
2013-10-07 14:35:29 105 100 2 Mark 1 John
2013-10-07 12:32:50 104 99 2 Mark 1 John
2013-10-07 12:15:43 104 98 2 Mark 1 John
2013-10-07 11:46:36 104 97 2 Mark 1 John
2013-10-07 11:43:32 104 96 1 John 2 Mark
2013-10-07 11:43:17 104 95 1 John 2 Mark
2013-10-07 11:27:14 103 94 1 John 2 Mark
What I want is this:
date_sent thread_id message_id sender_id sender_name recipient_id recipient_name
2013-10-09 14:31:50 106 113 1 John 2 Mark
2013-10-09 14:30:50 107 112 2 Mark 1 John
2013-10-09 09:49:58 112 110 1 John 2 Mark
2013-10-09 09:20:24 108 106 1 John 2 Mark
2013-10-07 14:40:25 103 104 1 John 2 Mark
2013-10-07 14:35:29 105 100 2 Mark 1 John
2013-10-07 12:32:50 104 99 2 Mark 1 John
Can this be done in one single query or should I create another query based upon the results of the first query?
Thank you for anyone that can help me solve this query....
Your various data sets, queries, and results do not appear to correspod with one another so it's a little difficult to follow, but I suspect you're after something along these lines...
SELECT m.message_id m_id
, m.sender_id s_id
, m.thread_id t_id
, m.subject
, m.message
, m.date_sent
, s.firstname sender
, r.firstname recipient
FROM message m
JOIN message_recipient n
ON n.message_id = m.message_id
JOIN user_public_info s
ON s.user_public_info_id = m.sender_id
JOIN user_public_info r
ON r.user_public_info_id = n.recipient_id
JOIN (SELECT thread_id, MAX(max_message_id) max_message_id FROM message GROUP BY thread_id)x
ON x.thread_id = m.thread_id AND x.max_message_id = m.message_id;

How to join a two tables compare with date?

Using Access 2003
Table1
Personid Date1
101 02-02-2008
102 02-02-2008
103 02-02-2008
101 03-02-2008
102 03-02-2008
103 03-02-2008
101 04-02-2008
102 04-02-2008
103 04-02-2008
So On…,
Table2
Personid Date1 Name Title
101 03-02-2008 Raja Accountant
102 04-02-2008 Ravi Supervisor
103 02-02-2008 Ram Manager
So on…,
I want to display all personid, date1 from table1 and name, title from table 2 where table2.date1 = table1.date
Expected Output:
Personid Date1 Name Title
101 02-02-2008
102 02-02-2008
103 02-02-2008 Ram Manager
101 03-02-2008 Raja Accountant
102 03-02-2008
103 03-02-2008
101 04-02-2008
102 04-02-2008 Ravi Supervisor
103 04-02-2008
So on…,
How to make a query for the above expected output.
Need Query Help
SELECT
Table1.personid,
Table1.date1,
Table2.name,
Table2.title
FROM Table1
LEFT JOIN Table2 ON Table1.date1 = Table2.date1
AND Table1.personid = Table2.personid;
Similar to mik's, but the AND at the end there is necessary, otherwise it applies the name and title to rows it doesn't belong in
SELECT Table1.personid, Table1.date1, Table2.name, Table2.title
FROM Table1 LEFT JOIN Table2 ON Table1.date1=Table2.date1;
This query should work