The task is to get know how much money player earned during the year.
So I want to write a select where by the known player_id I will aggregate his total win like.
FIRST_PLAYER_ID is an id of player who got the first place and FIRST_PRICE accordingly.
What I need:
player_id | total_prize_sum_over_all_tournaments_played_by_him
Code i tried so far:
SELECT PLAYER.SUNAME, TOURNAMENT.NAME FROM PLAYER
JOIN TOURNAMENT
ON PLAYER.ID = TOURNAMENT.FIRST_PLAYER_ID
OR PLAYER.ID = TOURNAMENT.SECOND_PLAYER_ID
OR PLAYER.ID = TOURNAMENT.THIRD_PLAYER_ID
ORDER BY PLAYER.BIRTH_DATE
Also, please help me to name this question correctly.
The following sql statement aggregates the prize money won by each player. The idea is to aggregate by each rank individually, summing up the results for each player afterwards.
SELECT pt.p_id
, SUM(pt.tl)
FROM (
SELECT p.p_id
, sum(t.first_prize) tl
FROM player p
JOIN tournament t on ( t.first_player_id = p.p_id )
GROUP BY p.p_id
UNION ALL
SELECT p.p_id
, sum(t.second_prize) tl
FROM player p
JOIN tournament t on ( t.second_player_id = p.p_id )
GROUP BY p.p_id
UNION ALL
SELECT p.p_id
, sum(t.third_prize) tl
FROM player p
JOIN tournament t on ( t.third_player_id = p.p_id )
GROUP BY p.p_id
) pt
GROUP BY pt.p_id
;
This sql fiddle is a full-fledged example (with restricted table definitons).
Related
I'm very new to learning SQL, I apologize if my question isn't completely accurate.
The question I'm trying to answer with this query is "What is the most popular music genre in each country?" I've had to use a subquery and it works, but I found that for a few countries in the table, more than one genre has the MAX value. I'm stuck with how to edit my query so that all genres with the max value show in the results. Here is my code, using DB Browser for SQLite:
SELECT BillingCountry AS Country , name AS Genre , MAX(genre_count) AS Purchases
FROM (
SELECT i.BillingCountry, g.name, COUNT(g.genreid) AS genre_count
FROM Invoice i
JOIN InvoiceLine il
ON il.InvoiceId = i.InvoiceId
JOIN TRACK t
ON il.trackid = t.TrackId
JOIN Genre g
ON t.genreid = g.GenreId
GROUP BY 1,2
) sub
GROUP BY 1
Here is an example of the result:
| Country | Genre |Purchase|
|---------|-------|--------|
|Agrentina| Punk | 9 |
|Australia| Rock | 22 |
BUT in running just the subquery to COUNT the purchases, Argentina has two Genres with 9 Purchases (the max number for that country). How do I adjust my query to include both and not just the first one in the row?
You can do it with RANK() window function:
SELECT BillingCountry, name, genre_count
FROM (
SELECT i.BillingCountry, g.name, COUNT(*) AS genre_count,
RANK() OVER (PARTITION BY i.BillingCountry ORDER BY COUNT(*) DESC) rnk
FROM Invoice i
INNER JOIN InvoiceLine il ON il.InvoiceId = i.InvoiceId
INNER JOIN TRACK t ON il.trackid = t.TrackId
INNER JOIN Genre g ON t.genreid = g.GenreId
GROUP BY i.BillingCountry, g.name
)
WHERE rnk = 1
This will return the ties in separate rows.
If you want 1 row for each country, you could also use GROUP_CONCAT():
SELECT BillingCountry, GROUP_CONCAT(name) AS name, MAX(genre_count) AS genre_count
FROM (
SELECT i.BillingCountry, g.name, COUNT(*) AS genre_count,
RANK() OVER (PARTITION BY i.BillingCountry ORDER BY COUNT(*) DESC) rnk
FROM Invoice i
INNER JOIN InvoiceLine il ON il.InvoiceId = i.InvoiceId
INNER JOIN TRACK t ON il.trackid = t.TrackId
INNER JOIN Genre g ON t.genreid = g.GenreId
GROUP BY i.BillingCountry, g.name
)
WHERE rnk = 1
GROUP BY BillingCountry
I have been stuck on this progressive question for more than 10 days now
Questions is :: Find all the actors that made more movies with Yash Chopra than any other director
Heres my attempt
SELECT pidsWhoDidMoviesWithYashChopra.pid,
pidsWhoDidMoviesWithYashChopra.moviesWithYashChopra,
pidsOfThoseWhoDidMoviesWithDirectors.moviesByAPID,
pidsWhoDidMoviesWithYashChopra.countOfMoviesWithYashChopraByAPID,
pidsOfThoseWhoDidMoviesWithDirectors.totalNumberOfMoviesByAPID
FROM
(
SELECT TRIM(M_Cast.PID) AS pid, moviesByYashChopra.mDirectorMID AS moviesWithYashChopra, COUNT(moviesByYashChopra.mDirectorMID) AS countOfMoviesWithYashChopraByAPID
FROM M_Cast
JOIN
(
SELECT TRIM(M_Director.MID) AS mDirectorMID
FROM
M_Director
WHERE TRIM(M_Director.PID) IN
(
SELECT TRIM(Person.PID) AS personPID
FROM
Person
WHERE Person.Name LIKE '%Yash Chopra%'
)
) AS moviesByYashChopra
ON TRIM(M_Cast.MID) == moviesByYashChopra.mDirectorMID
GROUP BY pid
) AS pidsWhoDidMoviesWithYashChopra
JOIN
(
SELECT TRIM(M_Cast.PID) AS pid, TRIM(M_Cast.MID) AS moviesByAPID, COUNT(TRIM(M_Cast.MID)) AS totalNumberOfMoviesByAPID
FROM M_Cast
GROUP BY pid
) AS pidsOfThoseWhoDidMoviesWithDirectors
ON pidsWhoDidMoviesWithYashChopra.pid == pidsOfThoseWhoDidMoviesWithDirectors.pid
GROUP BY pidsWhoDidMoviesWithYashChopra.pid
And here's the output it produces
And here's the schema
Now where I require help is :: Ability to go ahead from here :: As in how do i dissect this part of the question "than any other director." :: I think that's the tricky part
Any direction/hints will be helpful, Thanks...
You need to join person (for the actor's details) with m_cast, movie, m_director and person again (for the director's details) and group by actor and director to count the number of movies each actor made with each director.
Then use window functions first_value() to get the name of the director with whom the actor made the most movies and lag() to get the 2nd max number of movies (this is needed to filter out ties).
Enclose this query inside a CTE and then filter:
with cte as (
select pa.pid, pa.name, count(*) counter,
first_value(pd.name) over (partition by pa.pid, pa.name order by count(*) desc) max_dir_name,
lag(count(*)) over (partition by pa.pid, pa.name order by count(*) desc) prev_counter
from person pa
inner join m_cast c on c.pid = pa.pid
inner join movie m on m.mid = c.mid
inner join m_director d on d.mid = m.mid
inner join person pd on pd.pid = d.pid
group by pa.pid, pa.name, pd.name
)
select pid, name, counter
from cte
where max_dir_name = 'Yash Chopra' and coalesce(prev_counter, 0) < counter
I am trying to query the chinnok database to select sum of quantity tracks purchase and count the number of times the track appears in a playlist in one query.
Here is what I have:
/* Query 3 : which artist has the most songs on the top 100 songs across playlist and the most sold
songs*/
SELECT ar.Name Artist_Name, tr.Name Track_Name, count(pl.Name) Play_List, pt.TrackId Track_ID,
SUM(il.Quantity) Qty,
CASE WHEN count(pl.Name)=5 THEN "Five Stars"
ELSE "Four Star" END AS Ranking
FROM Track tr
JOIN PlaylistTrack pt
ON pt.TrackId = tr.TrackId
JOIN Playlist pl
ON pl.PlaylistId=pt.PlaylistId
JOIN Album ab
ON ab.AlbumId = tr.AlbumId
JOIN Artist ar
ON ar.ArtistId = ab.ArtistId
JOIN InvoiceLine il
ON il.TrackId = tr.TrackId
GROUP BY tr.TrackId
ORDER BY Play_List DESC
LIMIT 100;
Here is the results:
Fist 6 results
First 16 results
The Qty is correct but the Play_list number is not.
Can anyone help?
I have 3 Data Table Claim, Part and Labor.
In this Claim is parent table and Part and Labor is mapping tables of Claim and they have Part and Labor has the ClaimId as a Foreign Key.
Claim has data like:
Part has data Like
Labor table has data Like
Target Output would be:
Can anyone help me to achieve this in SQL server.
I have tried to solve with the Union/CTE but it did not gives the result as I want.
I got the same output (for your updated output screen) for this specific case. I don't know if any other data will work for you.
SELECT TMP.ClaimId
, CASE WHEN TMP.RowNum = 1 THEN TMP.Name ELSE NULL END AS ClaimName
, CASE WHEN TMP.RowNum = 1 THEN TMP.Note ELSE NULL END AS Note
, TMP.PartId
, TMP.PartNumber
, TMP.PartCost
, JOIN_L.LaborId
, JOIN_L.LaborCost
FROM (
SELECT C.ClaimId, C.Name, C.Note, P.PartId, P.PartNumber, P.PartCost
, ROW_NUMBER() OVER(PARTITION BY C.ClaimId ORDER BY P.PartId) AS RowNum
FROM Claim AS C
LEFT JOIN Part AS P ON C.ClaimId = P.ClaimId
)AS TMP
LEFT JOIN (
SELECT *
, ROW_NUMBER() OVER(PARTITION BY L.ClaimId ORDER BY L.ClaimId) AS RowNum
FROM Labor AS L
) AS JOIN_L ON (TMP.ClaimId = JOIN_L.ClaimId AND TMP.RowNum = JOIN_L.RowNum)
ORDER BY TMP.ClaimId
Not sure why you tried CTE here
Select C.ClaimId,C.name,C.Note,P.PartId,P.PartNumber,P.PartCost,L.LabourId,L.LabourCost
From Claim C
Left Outer Join Part P On P.ClaimId = C.ClaimId
Left Outer Join Labor L On L.ClaimId=C.ClaimId
I have query that runs as part of a function which produces a one row table full of counts, and averages, and comma separated lists like this:
select
(select
count(*)
from vw_disp_details
where round = 2013
and rating = 1) applicants,
(select
count(*)
from vw_disp_details
where round = 2013
and rating = 1
and applied != 'yes') s_applicants,
(select
LISTAGG(discipline, ',')
WITHIN GROUP (ORDER BY discipline)
from (select discipline,
count(*) discipline_number
from vw_disp_details
where round = 2013
and rating = 1
group by discipline)) disciplines,
(select
LISTAGG(discipline_count, ',')
WITHIN GROUP (ORDER BY discipline)
from (select discipline,
count(*) discipline_count
from vw_disp_details
where round = 2013
and rating = 1
group by discipline)) disciplines_count,
(select
round(avg(util.getawardstocols(application_id,'1','AWARD_NAME')), 2)
from vw_disp_details
where round = 2013
and rating = 1) average_award_score,
(select
round(avg(age))
from vw_disp_details
where round = 2013
and rating = 1) average_age
from dual;
Except that instead of 6 main sub-queries there are 23.
This returns something like this (if it were a CSV):
applicants | s_applicants | disciplines | disciplines_count | average_award_score | average_age
107 | 67 | "speed,accuracy,strength" | 3 | 97 | 23
Now I am programmatically swapping out the "rating = 1" part of the where clauses for other expressions. They all work rather quickly except for the "rating = 1" one which takes about 90 seconds to run and that is because the rating column in the vw_disp_details view is itself compiled by a sub-query:
(SELECT score
FROM read r,
eval_criteria_lookup ecl
WHERE r.criteria_id = ecl.criteria_id
AND r.application_id = a.lgo_application_id
AND criteria_description = 'Overall Score'
AND type = 'ABC'
) reader_rank
So when the function runs this extra query seems to slow everything down dramatically.
My question is, is there a better (more efficient) way to run a query like this that is basically just a series of counts and averages, and how can I refactor to optimize the speed so that the rating = 1 query doesn't take 90 seconds to run.
You could choose to MATERIALIZE the vw_disp_details VIEW. That would pre-calculate the value of the rating column. There are various options for how up-to-date a materialized view is kept, you would probably want to use the ON COMMIT clause so that vw_disp_details is always correct.
Have a look at the official documentation and see if that would work for you.
http://docs.oracle.com/cd/B28359_01/server.111/b28286/statements_6002.htm
Do all most of your queries in only one. Instead of doing:
select
(select (count(*) from my_tab) as count_all,
(select avg(age) from my_tab) as avg_age,
(select avg(mypkg.get_award(application_id) from my_tab) as_avg-app_id
from dual;
Just do:
select count(*), avg(age),avg(mypkg.get_award(application_id)) from my_tab;
And then, maybe you can do some union all for the other results. But this step all by itself should help.
I was able to solve this issue by doing two things: creating a new view that displayed only the results I needed, which gave me marginal gains in speed, and in that view moving the where clause of the sub-query that caused the lag into the where clause of the view and tacking on the result of the sub-query as column in the view. This still returns the same results thanks to the fact that there are always going to be records in the table the sub-query accessed for each row of the view query.
SELECT
a.application_id,
util.getstatus (a.application_id) status,
(SELECT score
FROM applicant_read ar,
eval_criteria_lookup ecl
WHERE ar.criteria_id = ecl.criteria_id
AND ar.application_id = a.application_id
AND criteria_description = 'Overall Score' //THESE TWO FIELDS
AND type = 'ABC' //ARE CRITERIA_ID = 15
) score
as.test_total test_total
FROM application a,
applicant_scores as
WHERE a.application_id = as.application_id(+);
Became
SELECT
a.application_id,
util.getstatus (a.application_id) status,
ar.score,
as.test_total test_total
FROM application a,
applicant_scores as,
applicant_read ar
WHERE a.application_id = as.application_id(+)
AND ar.application_id = a.application_id(+)
AND ar.criteria_id = 15;