SQL Group By Before Averaging - sql

Currently I have a query that finds the average of points scored depending upon opponent.
Here is the query:
SELECT NBAGameLog.Opp, AVG(NBAGameLog.Points)
FROM Players INNER JOIN
NBAGameLog
ON Players.Player_ID = NBAGameLog.Player_ID
WHERE (NBAGameLog.Date_Played Between Date()-15 And Date() AND
Players.Position = "C"
GROUP BY NBAGameLog.Opp;
The issue happens if I have something like this:
NBAGameLog table:
Player_ID Team Opp Points Position
1 MIA ATL 15 C
2 MIA ATL 25 C
3 BOS ATL 23 C
The result from this would be:
Position Opp Average
C ATL 21
But I'd like the query to first group together the Teams. So instead of (15+25+23)/3, it would see that the first two players were on the same team, so only count that as one and do (40+23)/2
Is this possible?

You can do this using a subquery, aggregating first in the subquery then again in the outer query:
SELECT t.Opp, avg(Points)
FROM (SELECT gl.team, gl.Opp, AVG(gl.Points) as Points
FROM Players p INNER JOIN
NBAGameLog gl
ON p.Player_ID = gl.Player_ID
WHERE (gl.Date_Played Between Date()-15 And Date() AND
p.Position = "C"
GROUP BY gl.team, gl.Opp;
) t
GROUP BY t.Opp;

Related

SQL Group rows in left join into one

i try create query with left join when i combine multiple rows into one. I try with GROUP_CONTENT function but when i try use it my db server is going down. I use MariaDB 10.3.17. I have tables like:
Games:
game_id game_name
1 Test
2 Stack
3 Other
data_developers:
dev_id dev_name
1 Electronic Arts
2 BioWare
3 2K Games
game_developers
developer_id game_id
1 1
2 1
2 3
Result i want:
game_id game_name devs
1 Test Electonics Arts, BioWare
2 Stack 2K Games
my two sql (but didnt work)
SELECT games.*, GROUP_CONCAT(data_developers.dev_name)
FROM games
LEFT JOIN game_developers ON game_developers.game_id = games.game_id
LEFT JOIN data_developers ON data_developers.dev_id = game_developers.dev_id
LIMIT 500
and second query
SELECT games.*
FROM games
LEFT JOIN game_developers ON game_developers.game_id = games.game_id
LEFT JOIN
(SELECT GROUP_CONCAT(data_developers.developer_name) as developers,
data_developers.developer_id FROM data_developers) x
ON x.developer_id = game_developers.developer_id
But of course, also dont work :(
Your query should be something like below-
SELECT A.game_id,B.Game_name,GROUP_CONCAT(C.dev_name)
FROM game_developers A
INNER JOIN Games B ON A.game_id = B.game_id
INNER JOIN data_developers C ON A.developer_id = C.dev_id
GROUP BY A.game_id,B.Game_name

SQL inquiry, tried absolutely everything I know, sql, four tables

I cant get this inquiry, tried like every thing
TABLE: ARTIST
JMBG NAME AGE ADRESA
--------------------------------------
J1 Ladygaga 35 HOLIVUDHILZ
J2 DUSKO 13 BB
J3 EMINEM 40 REVOLUCIJA 5
J4 BAGI 22 KURAC
J5 MARKO 33 ULICA
TABLE:HALL
DID CAPACITY CITY
---------------------------------
D1 500 PODGORICA
D2 300 NIS
D3 1000 BAR
D4 2000 NEWYORK
D5 750 BEOGRAD
TABLE: CITY
-----------------------------------------
BAR montenegro 5000
BEOGRAD Serbia 2000000
BUDVA montenegro 50000
NEWYORK AMERICA 7000000
NIS Serbia 1000000
PODGORICA montenegro 250000
TABLE: CONCERT
ID JMBG HALL
------------------------
K1 J3 D4
K2 J4 D1
K3 J1 D1
K4 J1 D5
K5 J1 D1
K6 J3 D1
K7 J5 D1
The inquiry is: Find the countries where the artist with the most held concerts
has performed in. I really did spend a lot of time on this and energy. I would greatly appreciate if someone could do this that has experience, and doesnt find it too difficult.
I tried this:
SELECT DISTINCT COUNTRY FROM CITY G, HALL D, CONCERT K
WHERE K.DID = D.DID AND D.NAZIV = G.NAZIV AND EXISTS(
SELECT JMBG FROM CONCERT K1,HALL D1, CITY G1
WHERE K.KID=K1.KID
GROUP BY JMBG
HAVING COUNT (*) >= ALL(SELECT COUNT(*) FROM CONCERT
GROUP BY JMBG))
Break it down. The artist with the most held concerts... Which artist had the most held concerts? (We're going to assume that we're interested in the total number of concerts held overall (in all countries), not the number of concerts held in a particular country.
How many concerts did each artist hold?
SELECT c.jmbg
, COUNT(1) AS cnt
FROM concert c
GROUP BY c.jmbg
Which artist held the most concerts? MySQL and MS SQL Server both have some convenient short cuts we can use here. A question we should ask here, what if there are two or more artists held the same number of concerts? Do we want to return both (or all) of those artists, or just return one of them? Which one? (We'd prefer the query to be deterministic... to return the same result given the same rows in the tables.)
Assuming that we want to return just one artist that held the most concerts...
For MySQL:
SELECT c.jmbg
FROM concert c
GROUP BY c.jmbg
ORDER BY COUNT(1) DESC, c.jmbg DESC
LIMIT 1
For SQL Server:
SELECT TOP 1 c.jmbg
FROM concert c
GROUP BY c.jmbg
ORDER BY COUNT(1) DESC, c.jmbg DESC
So that gets us the artist.
The other part of the "inquiry"... which countries did the artist hold concerts in.
Given a particular artist, we could write a query that performs join operations on the concert, hall and city tables. We'll just take a guess at the name of that first column in the city table (since it isn't provided in the question).
SELECT i.country
FROM city i
JOIN hall h
ON h.city = i.cid
JOIN concert o
ON o.hall = h.did
WHERE o.jmbg = 'Ladygaga'
GROUP BY i.country
To combine the two queries, we could use the first as a subquery. My preference is to use an inline view.
SELECT g.country
FROM city g
JOIN hall h
ON h.city = g.cid
JOIN concert o
ON o.hall = h.did
JOIN (
SELECT c.jmbg
FROM concert c
GROUP BY c.jmbg
ORDER BY COUNT(1) DESC, c.jmbg DESC
LIMIT 1
) m
ON m.jmbg = o.jmbg
GROUP BY g.country
Obviously, there are obviously other query patterns that will return an equivalent result.
As I noted in a comment on the question, the specification for this "inquiry" is a bit ambiguous, as to what is meant by "where the artist with the most held concerts has performed in".
There is another interpretation of that specification. If we're interested in getting and analyzing a count of "how many concerts were held in each country by each artist", that's a different query.
FOLLOWUP
"... not allowed to use TOP DESC"
Then just write the query differently. Here's a different way to get the "largest number of concerts held by any artist", and use that to get all the artists that all held that number of concerts.
SELECT n.jmbg
FROM ( -- largest number of concerts by artist
SELECT MAX(p.cnt) AS maxcnt
FROM (
SELECT COUNT(1) AS cnt
FROM concert d
GROUP BY d.jmbg
) p
) o
JOIN ( -- count of concerts by artist
SELECT c.jmbg
, COUNT(1) AS cnt
FROM concert c
GROUP BY c.jmbg
) n
ON n.cnt = o.maxcnt
Since that has the potential to return more than one row (more than one artist), your outer query may want to return a list of countries for each of the returned artists. That is to say, rather than just GROUP BY g.country, you'll likely want to return the artist in the SELECT list, and
GROUP BY m.jmbg, g.country
ORDER BY m.jmbg, g.country
This is a basic question that looks like coming out of school type of question. This answer will give you some hints but you need to work it out for yourself.
JOIN is your friend, find source below:
JOIN - MySQL
JOIN - SQL Server
What you need to do:
join CONCERT table with HALL table by HALL ID
join HALL table to CITY table by CITY name
sum the count of country appearance or hall capacity (either one you need) grouped by artist
order descending by the sum of count if you need it
Good luck

SQL MS Access join help average not correct

I am trying to create a query that displays the average attendance by conference when at least one team was in a game.
Relationships
this is very close to what im looking for
SELECT
Conference.ConferenceName,
AVG(Game.Attendance) AS AVG_ATT
FROM
(
Conference
INNER JOIN School ON Conference.[ConferenceID] = School.[ConferenceID]
)
INNER JOIN Game ON
(
School.[SchoolID] = Game.[Team1]
OR
School.[SchoolID] = Game.[Team2]
)
GROUP BY
Conference.ConferenceName;
the problem is if a game has 2 teams from the same conference it adds the attendance twice, and should only do it once.
consider 2 games
game1
Team1- Wisconsin
Conference - BIG10
Team2 - Michigan
Conference - BIG10
Attendance - 100,000
game2
Team1- Wisconsin
Conference - BIG10
Team2 - USC
Conference - PAC12
Attendance - 65,000
Results
BIG10-correct 82,500
PAC12 65,000
BIG10-Actual 88,333
Get a distinct list of the games by conference in a derived query, then do your average.
SELECT
ConferenceName,
AVG(Attendance) AS AVG_ATT
FROM
(
SELECT DISTINCT
GameID,
Conference.ConferenceName,
Game.Attendance
FROM
(
Conference
INNER JOIN School ON Conference.[ConferenceID] = School.[ConferenceID]
)
INNER JOIN Game ON
(
School.[SchoolID] = Game.[Team1]
OR
School.[SchoolID] = Game.[Team2]
)
) DerivedDistinctGamesAndConferences
GROUP BY
ConferenceName;
USE UNION to discard duplicated first before doing the average
SELECT
Game.GameID
Game.Attendance
Conference.ConferenceName
FROM
(
Conference
INNER JOIN School ON Conference.[ConferenceID] = School.[ConferenceID]
)
INNER JOIN Game ON
(
School.[SchoolID] = Game.[Team1] -- TEAM 1
)
UNION
SELECT
Game.GameID
Game.Attendance
Conference.ConferenceName
FROM
(
Conference
INNER JOIN School ON Conference.[ConferenceID] = School.[ConferenceID]
)
INNER JOIN Game ON
(
School.[SchoolID] = Game.[Team2] -- TEAM 2
)
So you will get query1 union query2
GameID Attendance Conference
1 100,000 BIG10 < one row will disapear
2 80,000 BIG10
1 100,000 BIG10 < after union
2 80,000 PAC12
Then you calculate the avergage over this result
I am not exactly sure in terms of coding, but conceptually, the fact that you need to aggregate totals "when at least one" team was- as you then say, only ONCE- at a conference, makes me intuit you may need to use some "if...then" clause statements within VBA script to get the specific calculation you want. Right now, the SQL "or" statement isn't enough.

How do I join to one row if there are several join matches?

I have 2 tables. I want to join in a way that the latest date is joined for that player. From the below subset, I want the join for Adams to only join to the row with the draw because it was the latest date-wise. How do I go about doing this when you have multiple rows?
ID PLAYER
-------------
2 Adams
3 Rogers
4 David
PLAYER_ID DATE RESULT
------------------------------------
2 01/01/2014 Win
2 01/02/2014 Win
2 01/03/2014 Loss
2 01/04/2014 Draw
I'm assuming player_id and date is a unique combination. Date isn't a good column name. I've assumed your tables names are player and result...in the future, give us table names so answers can include them instead of my guesses.
Building the query:
(select player_ID, max(date) from table group by player_ID)
That will select the maximum date for each player. We are going to use it as a subquery and inner join to it so it acts as a filter. Note that if the player_ID, date combination isn't unique, this will bring back multiple rows per player.
Select player, maxdate
from player p
inner join (select player_ID, max(date) as maxdate from result group by player_ID) a
on a.player_ID = p.player_ID
This will return to you a player and the most recent date. Join that back to the result table to get the result
Select player, result
from player p
inner join (select player_ID, max(date) as maxdate from result group by player_ID) a
on a.player_ID = p.player_ID
inner join result r on r.player_ID = a.player_ID and r.date = a.maxdate
Hopefully that makes sense as to the logic in creating the statement for you.

Finding group maxes in SQL join result [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
SQL: Select first row in each GROUP BY group?
Two SQL tables. One contestant has many entries:
Contestants Entries
Id Name Id Contestant_Id Score
-- ---- -- ------------- -----
1 Fred 1 3 100
2 Mary 2 3 22
3 Irving 3 1 888
4 Grizelda 4 4 123
5 1 19
6 3 50
Low score wins. Need to retrieve current best scores of all contestants ordered by score:
Best Entries Report
Name Entry_Id Score
---- -------- -----
Fred 5 19
Irving 2 22
Grizelda 4 123
I can certainly get this done with many queries. My question is whether there's a way to get the result with one, efficient SQL query. I can almost see how to do it with GROUP BY, but not quite.
In case it's relevant, the environment is Rails ActiveRecord and PostgreSQL.
Here is specific postgresql way of doing this:
SELECT DISTINCT ON (c.id) c.name, e.id, e.score
FROM Contestants c
JOIN Entries e ON c.id = e.Contestant_id
ORDER BY c.id, e.score
Details about DISTINCT ON are here.
My SQLFiddle with example.
UPD To order the results by score:
SELECT *
FROM (SELECT DISTINCT ON (c.id) c.name, e.id, e.score
FROM Contestants c
JOIN Entries e ON c.id = e.Contestant_id
ORDER BY c.id, e.score) t
ORDER BY score
The easiest way to do this is with the ranking functions:
select name, Entry_id, score
from (select e.*, c.name,
row_number() over (partition by e.contestant_id order by score) as seqnum
from entries e join
contestants c
on c.Contestant_id = c.id
) ec
where seqnum = 1
I'm not familiar with PostgreSQL, but something along these lines should work:
SELECT c.*, s.Score
FROM Contestants c
JOIN (SELECT MIN(Score) Score, Contestant_Id FROM Entries GROUP BY Contestant_Id) s
ON c.Id=s.Contestant_Id
one of solutions is
select min(e.score),c.name,c.id from entries e
inner join contestants c on e.contestant_id = c.id
group by e.contestant_id,c.name,c.id
here is example
http://sqlfiddle.com/#!3/9e307/27
This simple query should do the trick..
Select contestants.name as name, entries.id as entry_id, MIN(entries.score) as score
FROM entries
JOIN contestants ON contestants.id = entries.contestant_id
GROUP BY name
ORDER BY score
this grabs the min score for each contestant and orders them ASC