country with the highest number of tests(oracle plsql) - sql

Data Model:
Hi, I am trying to get "country with the highest number of tests".
Query:
I tried using one table.. ok... but how I get it with "countryname"? How should I make this with inner join?

Join, as you said.
select s.countryname,
s.date_,
s.total_tests
from (select
row_number() over (order by a.total_tests desc) rn,
a.date_,
a.total_tests,
c.countryname
from cases_by_countries a join country c
on c.countryid = a.country_id
) s
where s.rn = 1;

if you need only the highest you should try this
select c.CountryID, ts.Total_Tests
from Country c
inner join (
select top(1) Country_ID, Total_Tests
from CASES_BY_COUNTRIES
order by Total_Tests desc
) ts on c.CountryID = ts.Country_ID

Related

Table Joining Issues

I have difficulties joining the tables below for the desired query as stated.
Theatre (Theatre#, Name, Address, MainTel);
Production (P#, Title, ProductionDirector, PlayAuthor);
Performance (Per#, P#, Theatre#, pDate, pHour, pMinute, Comments);
Client (Client#, Title, Name, Street, Town, County, telNo, e-mail);
Ticket Purchase (Purchase#, Client#, Per#, PaymentMethod, DeliveryMethod, TotalAmount)
Required Query
The theater name (for each theater) and the names of clients who have the highest spending in that theater
SELECT T.NAME, C.NAME, SUM(TOTALAMOUNT)
FROM TICKETPURCHASE TP,
THEATRE T,
CLIENT C,
PERFORMANCE PER
WHERE TOTALAMOUNT = (SELECT MAX (TOTALAMOUNT)
FROM TICKETPURCHASE TP2,
THEATRE T2,
PERFORMANCE PER2,
CLIENT C2,
PRODUCTION P2
WHERE T2.NAME = T.NAME
AND T2.THEATRE# = PER2.THEATRE#
AND TP2.CLIENT# = C2.CLIENT#
AND TP2.PER# =PER2.PER#
AND PER2.P# = P2.P# )
AND C.CLIENT# = TP.CLIENT#
AND T.THEATRE# = PER.THEATRE#
AND TP.PER# = PER.PER#
AND PER.P# = P.P#
GROUP BY T.NAME, C.NAME, TOTALAMOUNT
From Oracle 12, you can do it all in a single query if you aggregate by the primary keys for the theatre and the client to get the total spent and then rank the spending in the ORDER BY clause and use the row limiting clause to get the first ranked values:
SELECT MAX(T.NAME) AS theatre_name,
MAX(C.NAME) AS client_name,
SUM(TP.TOTALAMOUNT) AS amount_spent
FROM TICKETPURCHASE TP
INNER JOIN PERFORMANCE PER
ON (TP.PER# = PER.PER#)
INNER JOIN THEATRE T
ON (T.THEATRE# = PER.THEATRE#)
INNER JOIN CLIENT C
ON (C.CLIENT# = TP.CLIENT#)
GROUP BY
T.THEATRE#,
C.CLIENT#
ORDER BY
DENSE_RANK() OVER (
PARTITION BY T.THEATRE#
ORDER BY SUM(TP.TOTALAMOUNT) DESC
)
FETCH FIRST ROW WITH TIES;
In earlier versions, you can use the same technique and filter in an outer query:
SELECT theatre_name,
client_name,
amount_spent
FROM (
SELECT MAX(T.NAME) AS theatre_name,
MAX(C.NAME) AS client_name,
SUM(TP.TOTALAMOUNT) AS amount_spent,
DENSE_RANK() OVER (
PARTITION BY T.THEATRE#
ORDER BY SUM(TP.TOTALAMOUNT) DESC
) As rnk
FROM TICKETPURCHASE TP
INNER JOIN PERFORMANCE PER
ON (TP.PER# = PER.PER#)
INNER JOIN THEATRE T
ON (T.THEATRE# = PER.THEATRE#)
INNER JOIN CLIENT C
ON (C.CLIENT# = TP.CLIENT#)
GROUP BY
T.THEATRE#,
C.CLIENT#
)
WHERE rnk = 1;

For each country, report the movie genre with the highest average rates

For each country, report the movie genre with the highest average ratings, and I am missing only one step that i cant figure it out.
Here's my current code:
SELECT c.code AS c_CODE, menres.genre AS GENRE, AVG(RATE) as AVERAGE_rate,MAX(RATE) AS MAXIMUM_rate, MIN(RATE) AS MINIMUM_rate from movirates
leftJOIN movgenres ON movgenres.movieid = movratings.movieid
left JOIN users ON users.userid = movrates.userid
left JOIN c ON c.code = users.city
LEFT JOIN menres ON movenres.genreid = menres.code
GROUP BY menres.genre , c.code
order by c.code asc, avg(rate) desc, menres.genre desc ;
You can use the ROW_NUMBER window function to assign a unique rank to each of your rows:
partitioned by country code
ordered by descendent average rating
Once you get this ranking, you may want to select all those rows which have the highest average rating (which are the same having the ranking equal to 1).
WITH cte AS (
SELECT c.code AS COUNTRY_CODE,
mg.genre AS GENRE,
AVG(rating) AS AVERAGE_RATING,
MAX(rating) AS MAXIMUM_RATING,
MIN(RATING) AS MINIMUM_RATING
FROM moviesratings r
INNER JOIN moviesgenres g ON g.movieid = r.movieid
INNER JOIN users u ON u.userid = r.userid
INNER JOIN countries c ON c.code = u.country
LEFT JOIN mGenres mg ON mg.code = g.genreid
GROUP BY mg.genre,
c.code
ORDER BY c.code,
AVG(rating) DESC,
mg.genre DESC;
)
SELECT *
FROM (SELECT *,
ROW_NUMBER() OVER(
PARTITION BY COUNTRY_CODE,
ORDER BY AVERAGE_RATING) AS rn
FROM cte) ranked_averages
WHERE rn = 1
Note: The code inside the common table expression is equivalent to yours. If you're willing to share your input tables, I may even suggest an improved query.
You should use window function in this case by using rank() then select the first rank only.
with mov_rates(c.code, genre, average, max, min)
as.
select c.code c_code,
e.genre genre,
avg (rate) avg
max (rate) max
min (rate) min
from movrates a
LEFT join movge.nres b on a.movieid = b.movieid
LEFT join users c on a.userid = c.user
LEFT join countr.ies d on c.code = d.code
left join mGenres e on b.genreid = e.code
group by d.country_code, e.x
),
rategenre (rank, c_code, genre, avgrate, max, min)
as
(
select rank() over (partition by c.c order by avgrates asc) rank,
country code,
genre,
average_r.ating,
maximum_rating,
minimum_.ating
from movrate \\just practicing on something
)
selec.t 2
from genre
where rank = 5
Reference:
OVER Clause

How can I show the maximum score of each department with their names

I can select maximum the score of each department but I can't show the name of each person associated with the max score.
I tried to select the name and the maximum grade (with maximum function) but it doesn't work:
select max(stgrade)as highscore,StName,DepName --department
from TBL_DEPARTMANTS d
inner join TBL_LESSONS l on d.DepID=l.LessonID
inner join TBL_GRADES g on g.lessonid=l.LessonID
inner join TBL_STUDENT s on s.STID=g.stid
group by DepName,StName
order by DepName,highscore desc
You may try this...
select * from ( select rank() over (partition by DepName order by stgrade desc) as Slno, stgrade, stname, DepName
from TBL_DEPARTMANTS d
inner join TBL_LESSONS l on d.DepID=l.LessonID
inner join TBL_GRADES g on g.lessonid=l.LessonID
inner join TBL_STUDENT s on s.STID=g.stid ) as dep where dep.slno=1
First create rank() in decreasing order of grade for individual department. then select top record for same.
Note: Use RANK() or DENSE_RANK(), both will work fine for top 1 record, while if you want to select n highest grade then use DENSE_RANK(), at the last for slno pass n'th record you want to select.
Always hard to do theory selects, but while DarkRob's solution is good, it will remove students if for instance two people are best. This is why I love using cross apply:
select
d.Depname
, s.StName
, g.stgrade
from TBL_DEPARTMANTS d
inner join TBL_LESSONS l on
d.DepID=l.LessonID
inner join TBL_GRADES g on
g.lessonid=l.LessonID
inner join TBL_STUDENT s on
s.STID=g.stid
cross apply (
select
sub_d.DepID
, max(sub_g.stgrade) as maxgrade
from TBL_DEPARTMANTS sub_d
inner join TBL_LESSONS sub_l on
sub_d.DepID=sub_l.LessonID
inner join TBL_GRADES sub_g on
sub_g.lessonid=sub_l.LessonID
where sub_d.Dep_ID = d.Dep_ID
group by sub_d.DepID
) as sub
where g.stgrade = sub.maxgrade
This way you will get all the people with max grade per department and not just one.

Display the city name which has most number of branches

I have tried to get city name which has most number of branches .
select C.City_name ,count(B.B_Name)
from tblcity C
inner join
tblBranch B
on c.city_id=B.City_id
group by C.City_name
order by count(B.B_Name) desc
Above code will give me the count of branches for particular city .
Please help me solve to get city name which has most number of branches
you can add TOP 1 to your query
select TOP 1 C.City_name ,count(B.B_Name)
from tblcity C
inner join
tblBranch B
on c.city_id=B.City_id
group by C.City_name
order by count(B.B_Name) desc
Use DENSE_RANK():
SELECT
City_Name, cnt
FROM
(
SELECT
c.City_name,
COUNT(b.B_Name) cnt,
DENSE_RANK() OVER (ORDER BY COUNT(b.B_Name) DESC) dr
FROM tblcity c
INNER JOIN tblBranch b
ON b.city_id = c.City_id
GROUP BY c.City_name
) t
WHERE dr = 1;
Using TOP 1 WITH TIES would be another option here, but that is specific to SQL Server.

oracle - maximum per group

University Table - UniversityName, UniversityId
Lease Table - LeaseId, BookId, UniversityId, LeaseDate
Book Table - BookId, UniversityId, Category, PageCount.
For each university, I have to find category that had the most number of books leased.
So, something like
UniversityName Category #OfTimesLeased
I have been playing around with it with some success using Dense_Rank etc - but if there is a tie, only one of them shows up, while I want both of them to show up.
Current Query:
select b.UniversityId, MAX(tempTable.type) KEEP (DENSE_RANK FIRST ORDER BY tempTable.counter DESC)
from book b
join
(select count(l.leaseid) AS counter, b.category, b.universityid
from lease l
join book b
on b.bookid =l.bookid AND b.universityid=r.universityid
group by b.category, b.universityid) tempTable
on counterTable.universityid= b.universityid
group by b.universityid
^Unable to solve the tie issue and get the number of leases for the most leased book type.
Try this
WITH CTE AS
(
SELECT UniversityName, Category, Count(*) NumOfTimesLeased
FROM University u
INNER JOIN Book b on u.UniversityId = b.UniversityId
INNER JOIN Lease l on b.bookid = l.bookid and b.UniversityId = l.UniversityId
GROUP BY UniversityName, Category
),
CTE2 AS (
SELECT UniversityName, Category, NumOfTimesLeased,
RANK() OVER (PARTITION BY UniversityName
ORDER BY NumOfTimesLeased DESC) Rnk
FROM CTE)
SELECT * FROM CTE2 WHERE Rnk = 1
You are on the right track with the analytic functions:
select Univerity, Category, NumLeased
from (select t.*,
row_number() over (partition by university order by Numleased desc) as seqnum
from (select l.university, b.category, count(*) as NumLeased
from lease l join
book b
on l.bookid = b.bookid
group by l.university, b.category
) t
) t
where seqnum = 1
I use the row_number() because you only want the one top value. Rank and dense_rank are more useful when you are looking for values other than "1".
If you want the top values to show up when there is a tie, then use dense_rank instead of row_number. The values will be on different rows.