I have this SQL query that does a GROUP BY to merge together all rows that contain the same Player_id but not the same Game_id:
SELECT p.Player_id,
p.Name,
p.Position,
SUM(s.Goals) AS goalsb,
SUM(s.Assists) AS assistsb,
SUM(s.Points) AS pointsb
FROM Dim_Player AS p
INNER JOIN Fact_Statistics AS s ON s.Player_id = p.Player_id
GROUP BY p.Player_id, p.Name, p.Position
ORDER BY pointsb DESC, goalsb DESC
What I want to do is implant a COUNT each time the GROUP BY merges a row with another to create a new column called "Games played". Example:
Player_id Game_id goalsb
8470598 465 1
8470598 435 1
this will be grouped together with the SQL query above to become:
Player_id goalsb
8470598 2
But I want to have this:
Player_id goalsb Games_played
8470598 2 2
If you have repeating Game_id's and you'd like to count the distinct values, you can add a
COUNT (DISTINCT Game_id)
clause to your SELECT statement.
Add a count function to the select query. COUNT(*) counts each row in the group, independent of the columns selected.
SELECT p.Player_id, p.Name, p.Position, SUM(s.Goals) AS goalsb, SUM(s.Assists) AS assistsb, SUM(s.Points) AS pointsb, COUNT(*) as [Games_played]
FROM Dim_Player AS p INNER JOIN Fact_Statistics AS s ON s.Player_id = p.Player_id
GROUP BY p.Player_id, p.Name, p.Position, s.Game_id
ORDER BY pointsb DESC, goalsb DESC
Related
I have to write a query that would calculate number of tickets purchased consisting only of movie genre of that type. At the end, I have to return movie genre and number of tickets bought for that genre. I have written a query but I was wondering if it can be made shorter and more compact?
Following is the database scheme:
movies(movieId, movieGenre, moviePrice)
tickets(ticketId, ticketDate, customerId)
details(ticketId, movieId, numOfTickets)
Here is my query:
select m.genre, count(*)
from(select t.ticketId, m.genre
from(select d.ticketId
from(select m.genre, t.ticketId
from tickets t join details d on t.ticketId =
d.ticketId join movies m on d.movieId = m.movieId
group by m.genre, t.ticketId) d
group by d.ticketId
having count(*) = 1) as t join details d on t.ticketId =
d.ticketId join movies m on d.movieId = m.movieId
group by t.ticketId, m.genre) m
group by m.genre;
This runs on a database so I am only able to post sample output:
comedy 29821
action 27857
rom-com 19663
I see no reason to use the table tickets, because the results do not filter or aggregate by ticketDate or customerID. Thus, a shorter sql is
SELECT m.moviegenre,
Sum(d.numoftickets) as SumNum
FROM details d
LEFT JOIN movies m
ON d.movieid = m.movieid
GROUP BY m.moviegenre
HAVING SumNum > 0
ORDER BY m.moviegenre
added 3/28 am
I am not sure what is meant by Duplicates?? In table = details(ticketId, movieId, numOfTickets) ??
I would expect that ticketId is unique, so what would explain duplicates?
Is the same ticketId being printed twice, repeatedly??
Determine what number of ticketId are duplicates--
SELECT ticketId, count(*) as cnt
FROM details d
GROUP By ticketId
HAVING count(*) > 1
Determine what number of "details" rows are duplicates--
SELECT ticketId, movieId, numOfTickets, count(*) as cnt
FROM details d
GROUP By ticketId, movieId, numOfTickets
HAVING count(*) > 1
Then again, it may be that table = movies(movieId, movieGenre, moviePrice) is the one with duplicates??
Determine what number of movieId are duplicates--
SELECT movieId, count(*) as cnt
FROM movies m
GROUP BY movieId
HAVING count(*) > 1
Remove duplicates from details--
SELECT m.moviegenre,
Sum(d.numoftickets) as SumNum
FROM
(Select Distinct * From details) d
LEFT JOIN movies m
ON d.movieid = m.movieid
GROUP BY m.moviegenre
ORDER BY m.moviegenre
I am trying to return the winner player in each group id, however, the group by function doesnt seem to work. Will appreciate your input on this.
SELECT
group_id,
player_id AS winner_id
FROM players AS p
LEFT JOIN (
SELECT
sum(first_score) AS total_first,
first_player
FROM matches
GROUP BY first_player
) AS a
ON p.player_id = a.first_player
LEFT JOIN (
SELECT
sum(second_score) as total_second,
second_player
FROM matches
GROUP BY second_player
) AS b
ON p.player_id = b.second_player
GROUP BY p.group_id
ORDER BY
coalesce(total_first, 0) + coalesce(total_second, 0) DESC,
player_id ASC
in your query no aggregate function so no need group by just use distinct
select distinct group_id, player_id as winner_id
from players as p
left join
(SELECT sum(first_score) as total_first, first_player
from matches
group by first_player) as a
on p.player_id = a.first_player
left join
(SELECT sum(second_score) as total_second, second_player
from matches
group by second_player) as b
on p.player_id = b.second_player
order by coalesce(total_first,0)+coalesce(total_second,0) desc, player_id asc
Assuming you want to have each field in levels of grouping, this may be a solution:
SELECT
group_id,
player_id AS winner_id
FROM players AS p
LEFT JOIN (
SELECT
sum(first_score) AS total_first,
first_player
FROM matches
GROUP BY first_player
) AS a
ON p.player_id = a.first_player
LEFT JOIN (
SELECT
sum(second_score) as total_second,
second_player
FROM matches
GROUP BY second_player
) AS b
ON p.player_id = b.second_player
GROUP BY
p.group_id,
p.player_id
ORDER BY
coalesce(total_first, 0) + coalesce(total_second, 0) DESC,
player_id ASC
When using GROUP BY you must specify sequence of all fields in grouping, so the statement is not ambiguous.
If I understand correctly, you want to sum the first and second score for each player, and then choose the one that has the highest value for the group.
So:
SELECT DISTINCT ON (p.group_id) p.group_id, v.player, SUM(score)
FROM matches m CROSS JOIN LATERAL
(VALUES (first_player, first_score),
(second_player, second_score)
) v(player, score) JOIN
players p
ON p.player_id = v.player
GROUP BY p.group_id, v.player
ORDER BY p.group_id, SUM(score) DESC;
Note that your LEFT JOIN approach is dangerous, because there might be some player, some time, some where, who is never first but always second.
I have this tables:
Student - Id, FirstName, LastName, Age
Group - Id, Name
Student_Group - Student_Id, Group_Id
I need to find least group of student. I have tried many times. I would be so glad if somebody helped.
Have you tried to do
SELECT top 1 g.name
FROM group g INNER JOIN Student_group sg ON g.id = sg.Group_Id
WHERE count(sg.student_id) >0
ORDER BY count(sg.student_id)
GROUP BY sg.group_id
?
If you want also the groups with 0 students you should to do
SELECT top 1 g.name
FROM group g INNER JOIN Student_group sg ON g.id = sg.Group_Id
ORDER BY count(sg.student_id)
GROUP BY sg.group_id
--If you just need the group with the least members,
--Group By and Count will work to find the Group with the least members
--Then use select top 1 record and order by GroupCount Ascending
SELECT TOP 1 Group_Id, COUNT(Group_Id) AS [GroupCount]
FROM Student_Group
GROUP BY Group_Id
ORDER BY [GroupCount]
I have three tables
1. players(id, first_name, last_name, age, position, team_id)
2. teams(id, team_name, stadium, wins, draws,defeats,goal_for,goal_against)
3. goals_scored(id, player_id, goal_time)
SQL statement
SELECT
players.first_name,
players.last_name,
teams.name,
players.position,
players.age,
COUNT(*) AS goals
FROM
players
JOIN goals_scored
ON players.id = goals_scored.player_id
JOIN teams
ON players.team_id = teams.id
GROUP BY players.id;
teams table
id team_name stadium wins draws defeats goal_for goal_against
1 APF Club Dasharath 7 2 7 29 25
players table
id first_name last_name position age team_id
4 Dipendra Shrestha forward 19 1
goals_scored table
id player_id goal_time
1 4 34
2 4 57
I want to group goals on players id so that I can get the count of goals of an individual player.
Like
first_name last_name team_name position age goals
Dipendra Shrestha APF Club forward 19 2
How can I do it?
Prefer to group on as few as possible columns, especially if multiple tables get involved so that a good index can be applied to handle the group by.
WITH GoalsPerPlayer (playerId, nrOfGoals)
AS
(
SELECT player_id, count(*)
FROM goals_scored
GROUP BY player_id
)
SELECT p.first_name, p.last_name, t.team_name, p.position, p.age, g.numberOfGoals as goals
FROM GoalsPerPlayer g
INNER JOIN players p ON p.id = g.player_id
INNER JOIN teams t ON t.id = p.team_id
Edit:
Fixed typo's in query as mentioned by PO in comment below.
WITH GoalsPerPlayer (playerId, nrOfGoals)
AS
(
SELECT player_id, count(*)
FROM goals_scored
GROUP BY player_id
)
SELECT p.first_name, p.last_name, t.team_name, p.position, p.age, g.nrOfGoals as goals
FROM GoalsPerPlayer g
INNER JOIN players p ON p.id = g.playerId
INNER JOIN teams t ON t.id = p.team_id
Your query basically looks fine. I would adjust the GROUP BY to be more complete:
SELECT p.first_name, p.last_name, t.name, p.position, p.age,
COUNT(*) AS goals
FROM players p JOIN
goals_scored gs
ON p.id = gs.player_id JOIN
teams t
ON p.team_id = t.id
GROUP BY p.first_name, p.last_name, t.name, p.position, p.age;
I need a help constructung an sql query for mysql database. 2 Table as follows:
tblcities (id,name)
tblmembers(id,name,city_id)
Now I want to retrieve the 'city' details that has maximum number of 'members'.
Regards
SELECT tblcities.id, tblcities.name, COUNT(tblmembers.id) AS member_count
FROM tblcities
LEFT JOIN tblmembers ON tblcities.id = tblmembers.city_id
GROUP BY tblcities.id
ORDER BY member_count DESC
LIMIT 1
Basically: retrieve all cities and count how many members each has, sort by that member count in descending order, making the highest count first - then show only that first city.
Terrible, but that's a way of doing it:
SELECT * FROM tblcities WHERE id IN (
SELECT city_id
FROM tblMembers
GROUP BY city_id
HAVING COUNT(*) = (
SELECT MAX(TOTAL)
FROM (
SELECT COUNT(*) AS TOTAL
FROM tblMembers
GROUP BY city_id
) AS AUX
)
)
That way, if there is a tie, still you'll get all cities with the maximum number of members...
Select ...
From tblCities As C
Join (
Select city_id, Count(*) As MemberCount
From tblMembers
Order By Count(*) Desc
Limit 1
) As MostMembers
On MostMembers.city_id = C.id
select top 1 c.id, c.name, count(*)
from tblcities c, tblmembers m
where c.id = m.city_id
group by c.id, c.name
order by count(*) desc