I have a table of students and a table of books that they borrowed. I need to find a student who borrowed the most books and show titles of these books.
Currently I have a list of students and number of books that each student borrowed, sorted descending. I can get the student who borrowed the most by using Top 1.
SELECT TOP 1 Students.Name, Students.LastName, Count(Books.Title) AS BorrowedBooksCount
FROM (Meldunek INNER JOIN Students ON Meldunek.pesel = Students.pesel)
INNER JOIN Books
ON Students.pesel = Books.pesel
GROUP BY Students.Name, Students.LastName
ORDER BY Count(Books.Title) DESC;
How to show names of books of a student who borrowed the most books?
To get the student who borrowed the most books:
select top 1 m.pesel
from Meldunek as m
group by m.pesel
order by count(*) desc;
You can use this in a where clause for filtering. But you should take into account that multiple students might have the same value. So, use in rather than =:
where s.pesel in (select top 1 m.pesel
from Meldunek as m
group by m.pesel
order by count(*) desc
);
This logic can be inserted into your query, so you return only the top borrowing students.
The complete query looks like:
select s.Name, s.LastName, b.Title
from (Meldunek as m inner join
Students s
on m.pesel = s.pesel
) inner join
Books as b
on s.pesel = b.pesel
where s.pesel in (select top 1 m2.pesel
from Meldunek as m2
group by m2.pesel
order by count(*) desc
);
Related
I'm trying to get to show only the category that have the most expensive item.
I tried and with the query I have I get all categories and the price of the most expensive item in every category, but I don't know how to do to just get just the one category that have the most expensive.
select categories.category ,max(purchase_price) as dyrast_bok
from categories
inner join books on categories.category_id = books.category_id
group by categories.category;
The tables:
CATEGORIES ( category_id (PK), category )
BOOKS ( book_id (PK), title, publisher_id (FK), published_year,
purchase_price, category_id (FK),purchase_date, pages,
book_type_id (FK) )
select categories.category ,purchase_price as dyrast_bok
from categories
inner join books on categories.category_id = books.category_id
where purchase_price in (select max(purchase_price) from books)
You can try to order by max(purchase_price) desc and take the first one:
select *
from (your query with order by max(purchase_price) desc)
limit 1
You just need to use aliases so you can reuse them in the GROUP BY part, and use top 1 to get only the highest result when you order by max(b.purchase_price).
This is how should be your query:
select top 1 c.category , max(b.purchase_price) as dyrast_bok
from categories c
inner join books b on categories.category_id = books.category_id
order by dyrast_bok
group by c.category;
Simple way: Have a sub-query that returns the max purchase_price.
select c.category, b.purchase_price as dyrast_bok
from categories c
inner join books b on c.category_id = b.category_id
where b.purchase_price = (select max(purchase_price) from books)
Will return both books in case of a tie!
Alternative solution:
select c.category, b.purchase_price as dyrast_bok
from categories c
inner join books b on c.category_id = b.category_id
order by b.purchase_price desc
fetch first 1 row
Will not include ties, only one row will be returned. (AFAIK Postgresql doesn't support FETCH FIRST WITH TIES.)
SELECT PEOPLE.TOWNKEY, TOWN_LOOKUP.TOWN FROM PEOPLE
INNER JOIN TOWN_LOOKUP
ON PEOPLE.TOWNKEY = TOWN_LOOKUP.PK
ORDER BY TOWN
Current Table Output:
You are missing the group by clause entirely:
SELECT tl.town, COUNT(*)
FROM people p
INNER JOIN town_lookup ON p.townkey = tl.pk
GROUP BY tl.town
ORDER BY tl.town
I have three tables:
Student(StudentID, StudentName)
Course(CourseID, CourseName)
StudentCourse(StudentID, CourseID) -- junction table to assign courses to students
How would I query to get the favourite course--"the course which has highest number of students enrolled"?
SQLFiddle
Try it by using TOP...WITH TIES
SELECT TOP 1 WITH TIES c.CourseName,
COUNT(c.CourseID) totalCount
FROM student a
INNER JOIN studentcourse b
ON a.studentID = b.studentID
INNER JOIN course c
ON b.courseID = c.courseID
GROUP BY c.CourseName
ORDER BY totalCount DESC
WITH TIES show the records that have the same highest number of counts.
SQLFiddle Demo
SELECT TOP 1 WITH TIES COURSEID
FROM STUDENTCOURSE
GROUP BY COURSEID
ORDER BY Count(*) DESC
I have this SQL Server query which I wrote to find the Movie title that has the least amount of records in the RENTAL table.
When run, it returns a resultset that is identical to the resultset I get from executing the sub-query by itself.
In other words, rather returning the single movie with the minimum RentalCount, it returns all movie titles and their corresponding RentalCount.
SELECT B.Title, MIN(B.RentalCount) AS RentalCount
FROM (
SELECT Movie.Title, Count(*) AS RentalCount
FROM Rental
JOIN Dvd ON Rental.RentalID=Dvd.DvdID
JOIN Movie ON Dvd.Movieid=movie.MovieID
GROUP BY Movie.Title
) B
GROUP BY B.Title
The result is correct. Your subquery returns the total count for each title on the rental table. And the result will be the same on the outer query because you have grouped them by their title also.
follow-up question: what result do you want to achieved?
find the Movie title that has the least amount of records in the RENTAL table
SELECT Movie.Title, Count(*) AS RentalCount
FROM Rental
JOIN Dvd ON Rental.RentalID=Dvd.DvdID
JOIN Movie ON Dvd.Movieid=movie.MovieID
GROUP BY Movie.Title
HAVING Count(*) =
(
SELECT MIN(t_count)
FROM
(
SELECT Count(*) t_count
FROM Rental
GROUP BY Title
) a
)
UPDATE 1
Thanks to Martin Smith for introducing me TOP....WITH TIES
SELECT TOP 1 WITH TIES Movie.Title, Count(*) AS RentalCount
FROM Rental
JOIN Dvd ON Rental.RentalID=Dvd.DvdID
JOIN Movie ON Dvd.Movieid=movie.MovieID
GROUP BY Movie.Title
ORDER BY RentalCount DESC
SQLFiddle Demo
You could have done this without a subquery
SELECT TOP 1 Movie.Title, Count(*) AS RentalCount
FROM Rental
JOIN Dvd ON Rental.RentalID=Dvd.DvdID
JOIN Movie ON Dvd.Movieid=movie.MovieID
GROUP BY Movie.Title
ORDER BY Count(*)
if you are looking for a specfic movie title then do like this:
SELECT Movie.Title, Count(*) AS RentalCount
FROM Rental
JOIN Dvd ON Rental.RentalID=Dvd.DvdID
JOIN Movie ON Dvd.Movieid=movie.MovieID
where Movie.Title='xyz'
GROUP BY Movie.Title
There are three tables:
A table about students: s41071030(sno, sname, ssex, sage, sdept)
A table about course: c41071030(cno, cname, cpno, credit)
A table about selecting courses: sc41071030(sno, cno, grade)
Now, I want select the details about a student whose sdept='CS' and he or she has selected the most courses in department 'CS'.
As with any modestly complex SQL statement, it is best to do 'TDQD' — Test Driven Query Design. Start off with simple parts of the question and build them into a more complex answer.
To find out how many courses each student in the CS department is taking, we write:
SELECT S.Sno, COUNT(*) NumCourses
FROM s41071030 S
JOIN sc41071030 SC ON S.Sno = SC.Sno
WHERE S.Sdept = 'CS'
GROUP BY S.Sno;
We now need to find the largest value of NumCourses:
SELECT MAX(NumCourses) MaxCourses
FROM (SELECT S.Sno, COUNT(*) NumCourses
FROM s41071030 S
JOIN sc41071030 SC ON S.Sno = SC.Sno
WHERE S.Sdept = 'CS'
GROUP BY S.Sno
)
Now we need to join that result with the sub-query, so it is time for a CTE (Common Table Expression):
WITH N AS
(SELECT S.Sno, COUNT(*) NumCourses
FROM s41071030 S
JOIN sc41071030 SC ON S.Sno = SC.Sno
WHERE S.Sdept = 'CS'
GROUP BY S.Sno
)
SELECT N.Sno
FROM N
JOIN (SELECT MAX(NumCourses) MaxCourses FROM N) M
ON M.MaxCourses = N.NumCourses;
And we need to get the student details, so we join that with the student table:
WITH N AS
(SELECT S.Sno, COUNT(*) NumCourses
FROM s41071030 S
JOIN sc41071030 SC ON S.Sno = SC.Sno
WHERE S.Sdept = 'CS'
GROUP BY S.Sno
)
SELECT S.*
FROM s41071030 S
JOIN N ON N.Sno = S.Sno
JOIN (SELECT MAX(NumCourses) MaxCourses FROM N) M
ON M.MaxCourses = N.NumCourses;
Lightly tested SQL: you were warned. To test, run the component queries, making sure you get reasonable results each time. Don't move on to the next query until the previous one is working correctly.
Note that the courses table turns out to be immaterial to the query you are solving.
Also note that this may return several rows if it turns out there are several students all taking the same number of courses and that number is the largest number that any student is taking. (So, if there are 3 students taking 7 courses each, and no student taking more than 7 courses, then you will see 3 rows in the result set.)
Aggregate sc41071030 rows to get the counts.
Join the results to s41071030 to:
filter rows on sdept;
get student details;
RANK() the joined rows on the count values.
Select rows with the ranking of 1.
WITH
aggregated AS (
SELECT
sno,
COUNT(*) AS coursecount
FROM
sc41071030
GROUP BY
sno
),
ranked AS (
SELECT
s.*,
RANK() OVER (ORDER BY agg.coursecount DESC) AS rnk
FROM
s41071030 s
INNER JOIN aggregated agg ON s.sno = agg.sno
WHERE
s.sdept = 'CS'
)
SELECT
sno,
sname,
ssex,
sage,
sdept
FROM
ranked
WHERE
rnk = 1
;