image1 image2I am trying to write an sql function to show the year, playername, and ppg of the player with the highest ppg from each year in our database.
We have a Players table with all the stats, and a team table with stats linked to each season as a team total.
What I want to do is get the highest scorer from each season so:
2010: Jake 10ppg
2011: Jake 12 ppg
2012 Carl 13 ppq
Etc.
here is my current query
SELECT Year, PlayerName, MAX(PPG) AS PPG
FROM PLAYERS_T, TEAM_T
GROUP BY Year
ORDER BY PPG;
However this is not working, what do I need to do to make this work?
This should work, but will show duplicated record if same PPG. Dont know what is the use of Team table there
SQL DEMO
WITH PLAYERS_T as (
SELECT 2010 "Year", 'Jake' "PlayerName", 10 ppg
UNION
SELECT 2011 "Year", 'Jake' "PlayerName", 12 ppg
UNION
SELECT 2012 "Year", 'Carl' "PlayerName", 13 ppg
)
SELECT T1."Year", T1."PlayerName", T1.PPG
FROM PLAYERS_T T1
LEFT JOIN PLAYERS_T T2
ON T1."Year" = T2."Year"
AND T1.PPG < T2.PPG
WHERE T2."Year" IS NULL
OUTPUT
Try this one:
SELECT players_T.playername, players_T.ppg, players_T.year
FROM
(SELECT year, MAX(PPG) AS mx
FROM players_T
GROUP BY year) sub
INNER JOIN players_T ON sub.mx = players_T.ppg
WHERE sub.year = players_T.year
ORDER BY players_T.year
In the subquery, this finds the max ppg per year. Then we join with the players table on the ppg to find the player name. The result should be the player name, ppg and year together. Let me know what you find!
Edit: Need to include a WHERE clause for year
Related
Struggling to go the extra step with a SQL query I'd like to run.
I have a customer database with a Customer table with the date/time detail of when the customer joined and a transaction table with details of their transactions of the years
What I'd like to do is to Group by the Join Date (as Year) and count the number that joined in each year then in the next column I'd like to then count the number who have transacted in a specific year E.g. 2016 the current year. This way I can show customer retention over the years.
Both tables are linked by a customer URN, but I am struggling to get my head around the the most efficient way to show this. I can easily count and group the members by joined year and I can display the max dated transaction but I am struggling to bring the two together. I think I need to use sub queries and a left join but it's alluding me.
Example output column headers with data
Year_Joined = 2009
Joiner_Count = 10
Transact_in_2016 = 5
Where I am syntax-wise. I know this is no where near complete. As I need to group by DateJoined and then sub query the count of customers of have transacted in 2016?
SELECT Customer.URNCustomer,
MAX(YEAR(Customer.DateJoined)),
MAX(YEAR(Tran.TranDate)) As Latest_Tran,
FROM Mydatabase.dbo.Customer
LEFT JOIN Mydatabase.dbo.Tran
ON Tran.URNCustomer = Customer.URNCustomer
GROUP BY Customer.URNCustomer
ORDER BY Customer.URNCustomer
The best approach is to do the aggregation before doing the joins. You want to count two different things, so count them individually and them combine them.
The following uses full outer join. This handles the case where there are years with no new customers and years with no transactions:
select coalesce(c.yyyy, t.yyyy) as yyyy,
coalesce(c.numcustomers, 0) as numcustomers,
coalesce(t.numtransactions, 0) as numtransactions
from (select year(c.datejoined) as yyyy, count(*) as numcustomers
from Mydatabase.dbo.Customer c
group by year(c.datejoined)
) c full outer join
(select year(t.trandate) as yyyy, count(*) as numtransactions
from database.dbo.Tran t
group by year(t.trandate)
) t
on c.yyyy = t.yyyy;
You may want to try something like this:
SELECT YEAR(Customer.DateJoined),
COUNT( Customer.URNCustomer ),
COUNT( DISTINCT Tran.URNCustomer ) AS NO_ACTIVE_IN_2016
FROM Mydatabase.dbo.Customer
LEFT Mydatabase.dbo.Tran
ON Tran.URNCustomer = Customer.URNCustomer
AND YEAR(Tran.TranDate) = 2016
GROUP BY YEAR(Customer.DateJoined)
I have database of library and i am trying to assign most borrowed title to each year like
2015 - The Great Gatsby
2014 - Da vinci code
2013 - Harry Potter
....
I've tried this but i am not sure about it
select to_char(borrow_date,'YYYY'),title_name
from k_title
join k_book
using(title_id)
join k_rent_books
using(book_id)
group by to_char(borrow_date,'YYYY'),title_name
having count(title_id) = (
select max(cnt) FROM(select count(title_name) as cnt
from k_title
join k_book
using(title_id)
join k_rent_books
using(book_id)
group by title_id,title_name,to_char(borrow_date,'YYYY')));
I've got only 3 results
2016 - Shogun
2006 - The Revolt of Mamie Stover
1996 - The Great Gatsby
I will be happy for any help :)
Oracle has the nice capability to get the first or last value in an aggregation (as opposed to the min() or max()). This requires using something called keep.
So, the way to express what you want to do is:
select yyyy,
max(title_name) keep (dense_rank first order by cnt desc) as title_name
from (select to_char(borrow_date, 'YYYY') as yyyy,
title_name, count(*) as cnt
from k_title t join
k_book b
using (title_id) join
k_rent_books
using (book_id)
group by to_char(borrow_date, 'YYYY'), title_name
) yt
group by yyyy;
Your query is returning the year/title combinations that have the overall maximum count over all years, not the maximum per year.
Title may not make sense so I will provide some context.
I have a table, call it Movies.
A movie tuple has the values: Name, Director, Genre, Year
I'm trying to create a query that allows me to return all Directors who have never released two consecutive Horror films with more than 4 years apart.
I'm not sure where I'd begin but I'm trying to start off by creating a query that given some specific year, returns the next minimum year, so that I can check if the difference between these two is less than 4, and keep doing that for all movies.
My attempt was:
SELECT D1.Director
FROM Movies D1
WHERE D1.Director NOT IN
(SELECT D2.Director FROM Director D2
WHERE D2.Director = D1.Director
AND D2.Genre = 'Horror'
AND D1.Genre = 'Horror' AND D2.Year - D1.Year > 4
OR D1.Year - D2.Year > 4)
which does not work for obvious reasons.
I've also had a few attempts using joins, and it works on films that follow a pattern such as 2000, 2003, 2006, but fail if more than 3 films.
You could try this:
Select all data, and use lag or lead to return the last or next year. After that look at the difference between the two.
WITH TempTable AS (
SELECT
Name,
Director,
Genre,
Year,
LAG(Year) OVER (PARTITION BY Name, Director, Genre ORDER BY Year ASC) AS 'PriorYear'
FROM
Movies
WHERE
Genre = 'Horror'
)
SELECT
Name,
Director
FROM
TempTable
GROUP BY
Name,
Director
HAVING
MAX(Year-PriorYear) < 2
Try this:
SELECT * FROM (
SELECT director, min(diff) as diff FROM (
SELECT m1.director, m1.year as year1, m2.year as year2, m2.year-m1.year as diff
FROM `movies` m1, movies m2
WHERE m1.director = m2.director and m1.name <> m2.name and m1.year<=m2.year
and m1.genre='horror' and m2.genre='horror'
) d1 group by director
) d2 WHERE diff>4
First, in the inner Select it will list all movie pairs of directors' horror movies with year difference calculated, then minimum of these are selected (for consecutiveness), then longer than 4 years differences are selected...
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 8 years ago.
Improve this question
Table Structure:
Article(
model int(key),
year int(key),
author varchar(key),
num int)
num: number of articles wrote during the year
Find all the authors that each one of them in one year atleast wrote maximal number of articles (relative to all the other authors)
I tried:
SELECT author FROM Article,
(SELECT year,max(sumnum) s FROM
(SELECT year,author,SUM(num) sumnum FROM Article GROUP BY year,author)
GROUP BY year) AS B WHERE Article.year=B.year and Article.num=B.s;
Is this the right answer?
Thanks.
You might want to try a self-JOIN to get what you are looking for:
SELECT Main.author
FROM Article AS Main
INNER JOIN (
SELECT year
,author
,SUM(num) AS sumnum
FROM Article
GROUP BY year
,author
) AS SumMain
ON SumMain.year = Main.year
AND SumMain.author = Main.author
GROUP BY Main.author
HAVING SUM(Main.num) = MAX(SumMain.sumnum)
;
This would guarantee (as it is ANSI) you are getting the MAX of the SUMmed nums and only bringing back results for what you need. Keep in mind I only JOINed on those two fields because of the information provided ... if you have a unique ID you can JOIN on, or you require more specificity to get a 1-to-1 match, adjust accordingly.
Depending on what DBMS you are using, it can be simplified one of two ways:
SELECT author
FROM (
SELECT year
,author
,SUM(num) AS sumnum
FROM Article
GROUP BY year
,author
HAVING SUM(num) = MAX(sumnum)
) AS Main
;
Some DBMSes allow you to do multiple aggregate functions, and this could work there.
If your DBMS allows you to do OLAP functions, you can do something like this:
SELECT author
FROM (
SELECT year
,author
,SUM(num) AS sumnum
FROM Article
GROUP BY year
,author
) AS Main
QUALIFY (
ROW_NUMBER() OVER (
PARTITION BY author
,year
ORDER BY sumnum DESC
) = 1
)
;
Which would limit the result set to only the highest sumnum, although you may need more parameters to handle things if you wanted the year to be involved (you are GROUPing by it, only reason I bring it up).
Hope this helps!
You mention for homework and a valid attempt, however incorrect.
This is under a premise (unclear since no sample data) that the model column is like an auto-increment, and there is only going to be one entry per author per year and never multiple records for the same author within the same year. Ex:
model year author num
===== ==== ====== ===
1 2013 A 15
2 2013 C 18
3 2013 X 17
4 2014 A 16
5 2014 B 12
6 2014 C 16
7 2014 X 18
8 2014 Y 18
So the result expected is highest article count in 2013 = 18 and would only return author "C". In 2014, highest article count is 18 and would return authors "X" and "Y"
First, get a query of what was the maximum number of articles written...
select
year,
max( num ) as ArticlesPerYear
from
Article
GROUP BY
year
This would give you one record per year, and the maximum number of articles published... so if you had data for years 2010-2014, you would at MOST have 5 records returned. Now, it is as simple as joining this to the original table that had the matching year and articles
select
A2.*
from
( select
year,
max( num ) as ArticlesPerYear
from
Article
GROUP BY
year ) PreQuery
JOIN Article A2
on PreQuery.Year = A2.Year
AND PreQuery.ArticlesPerYear = A2.num
I suggest a CTE
WITH maxyear AS
(SELECT year, max(num) AS max_articles
FROM article
GROUP BY year)
SELECT DISTINCT author
FROM article a
JOIN maxyear m
ON a.year=m.year AND a.num=m.max_articles;
and compare that in performance to a partition, which is another way
SELECT DISTINCT author FROM
(SELECT author, rank() AS r
OVER (PARTITION BY year ORDER BY num DESC)
FROM article) AS subq
WHERE r = 1;
I think some RDBMS will let you put HAVING rank()=1 on the subquery and then you don't need to nest queries.
I have the following table.
I need to select SemesterID,AcadamiYear,AcademicSemester of the record with highest Academic year and Academic semester of the year 2015
Expected output is
2013 1 2
I tried the following query but it returns both of the records
select MAX(AcadamiYear) as Year,
MAX(AcadamicSemester) as Semester
,SemesterID
from
tblSemesterRegistration
where [IntakeYear]='2015'
Group by SemesterID
Since you are searching for a single record you might use TOP 1, ordered by your intend
select TOP 1 *
from
tblSemesterRegistration
where [IntakeYear]='2015'
Order by AcadamiYear DESC, AcadamicSemester DESC
This is the query you're looking for:
SELECT SR.*
FROM tblSemesterRegistration SR
INNER JOIN (SELECT MAX(SR2.AcadamiYear) AS [AcadamiYear]
,MAX(SR2.AcadamicSemester) AS [AcadamicSemester]
,IntakeYear
FROM tblSemesterRegistration SR2
GROUP BY SR2.IntageYear) T ON T.AcadamiYear = SR.AcadamiYear
AND T.AcadamicSemester = SR.AcadamicSemester
AND T.IntakeYear = SR.IntakeYear
WHERE SR.IntakeYear = '2015'
Hope this will help you.
If SemesterID is the primary key, grouping on it will always yield all rows (since it is always unique).
I guess you mean to find back that semester id with the parameters set:
select r.*
from tblSemesterRegistration r
join ( select max(AcadamiYear) as Year
, max(AcadamicSemester) as Semester
from tblSemesterRegistration
where [IntakeYear]='2015'
) m
on r.acadamiyear = m.year
and r.acadamicsemester = m.semester
SELECT MAX(AcadamiYear) AS Year,
MAX(AcademicSemester) AS Semester,
MAX(SemesterID) AS SemesterID
FROM tblSemesterRegistration
WHERE [IntakeYear] = '2015'
GROUP BY IntakeYear