Trouble With GROUP BY Learning Derby SQL - sql

I have formed this query to produce the pitcher from each team who has the most wins. My trouble comes in that I need to group them a certain way and I keep having scoping issues when trying to do so. W is the number of wins for each pitcher. Here is my pre-grouped statement...
SELECT
(SELECT p1.nameFirst FROM Players p1 Where (one.playerID = p1.playerID)),
(SELECT p1.nameLast FROM Players p1 Where (one.playerID = p1.playerID)),
one.W, (SELECT t1.name FROM Teams t1 Where(one.teamID = t1.teamID))
FROM Pitching one
Where (one.W >= ALL
(SELECT two.W
FROM Pitching two
Where (two.teamID = one.teamID)));
I need to group the tuples by league and within the leagues group by division. League (lgID) and division (divID) exist in the Teams table. Can someone point me in the right direction? Thank you.
This is top six rows of what is currently output...
Zach Britton 11 Baltimore Orioles
Mark Buehrle 13 Chicago White Sox
Madison Bumgarner 13 San Francisco Giants
Jhoulys Chacin 11 Colorado Rockies
Bruce Chen 12 Kansas City Royals
Kevin Correia 12 Pittsburgh Pirates
My desired output is to have these teams sorted by league (NL/AL) and within the leagues have them sorted by division.

Based on your updated comment. I think this is what you want.
SELECT
pl.nameFirst
, pl.nameLast
, p.W
, t.name
FROM
(
SELECT
MAX(p1.W) AS W
, p1.teamId
FROM
Pitching p1
GROUP BY
p1.teamId
) t1
JOIN
Pitching p
ON t1.W = p.W
AND t1.teamId = p.teamId
JOIN
Players pl
ON p.playerID = pl.playerID
JOIN
Teams t
ON p.teamID = t.teamID
ORDER BY
t.lgID
, t.divID
I do agree with swasheck, there are some opportunities for improvement in your schema. As swascheck said, teamId should be in Players. Not in Pitching.

This may be an issue of structure. Using what I believe to be your structure we could probably narrow it down like this:
select Players.nameFirst, Players.nameLast, TopPitcher.Winner,
Teams.name, League.Name, Division.Name
from (select playerID, max(Wins) as Winner
from (select playerID, teamID, count(W) as Wins
from Pitching
group by playerID, teamID ) PitchingWins) TopPitcher
join Players
on TopPitcher.playerID = Players.playerID
join Teams
on Teams.teamID = Players.teamID
join League
on Teams.leagueID = League.leagueID
join Division
on League.divisionID = Division.divisionID
order by League.Name, Division.Name
Now. Having said that, this is only for the structure you've given (with some other interpolation). Your overall structure is faulty as I would probably relate Player to Teams and not Pitching to Teams since you might get some sort of data errors regarding team wins vs. pitcher wins.

Related

How to join few table and connect id with name column from another table

I have these tables with the following column names:
players:
id first_name last_name age position salary hire_date skills_data_id team_id
Skills:
id, dribbling, pace, passing, shooting, speed, strength
towns:
id, name, country_id
teams:
id name established fan_base stadium_id
On this base, I have found the players with the max speed in terms of towns where their team played.
At the same time, I have to skip players that played in team ‘Devify’.
At the moment I have tried with this code, but the final result is not correct.
select max(s.speed) as `max_speed`,tt.name as `town_name`
from skills_data as s
right join players as p on s.id = p.skills_data_id
inner join teams as t on p.team_id = t.id
inner join towns as tt on p.team_id = tt.id
where t.name not like 'Devify'
group by s.id
order by max(s.speed) desc, town_name;
The result should be something like that:
max_speed town_name
97 Smolensk
92 Bromma
92 Lühua
...
NULL Zavolzh’ye
My result is:
max_speed town_name
97 Montréal-Ouest
92 Dalubian
92 Samsan
Thank you in advance.
There is a problem in your group by clause: you should be grouping by town rather than by skill id.
I am also quite suspicious about the join condition that brings in the towns (see my comment under your question): but if you are getting results for your existing query, it must be right...
Other changes to your query:
changed your right join to an inner join
used more meaningful table aliases
used an inequality condition instead of not like to exclude the unwanted team
New query:
select
max(sk.speed) as max_speed,
to.name as `town_name`
from skills_data as sk
inner join players as pl on sk.id = pl.skills_data_id
inner join teams as te on pl.team_id = te.id and te.name <> 'Devify'
inner join towns as to on pl.team_id = to.id
group by to.id, to.name
order by max_speed desc, town_name;

three tables relations SQL select

I'm learning SQL, so help is greatly appreciated.
I have three tables: league, player and team
league and player is many to many (as a player can be in more than one league)
team and player is many to many (as a player can be on a team in multiple leagues)
league and team is one to many.
I have the following table ids:
league.id ----. league_has_player (league_id, player_id) .------ player.id
team.id ----. team_has_player (team_id, player_id) .----- player.id
league ----. team.id (team.league_id)
I want to get all the players in the league who are not on a team in the league.
Here's my broken attempt.
Select *
from player p,
join team t on t.league_id = l.id
join league l on league.id = 2
where p.id = league_has_player.player_id and
not in (select team_has_player.player_id from team_has_player)
I think you're trying more for something like this. As a couple comments have pointed out, your table schema isn't clear. But this is the impression I get from your attempt.
DECALRE #leagueId...
SELECT *
FROM player
WHERE player.id IN (SELECT player_id
FROM league_has_player
WHERE league_id = #leagueId) AND
player.id NOT IN (SELECT player_id
FROM team_has_player
INNER JOIN team ON team.Id = team_has_player.team_id
WHERE team.league_id = #leagueId)
Get all the players registered for the league, where they don't belong to a team in the league.
SELECT p.*, lp.league_id
FROM player p
JOIN league_has_player lp ON lp.player_id = p.id
WHERE NOT EXISTS (select 1
FROM team_has_player tp
JOIN team t ON t.id = tp.team_id
AND tp.player_id = p.player_id
AND t.league_id = lp.league_id)

New to SQL, having trouble with table with two IDs

I have a DB of scores over the course of a season and I am having trouble with a query to return the season results for a given team. Here is a snapshot of the table involved:
Teams (tid, team_name)
Games (home_team_id, road_team_id, game_date, home_score, road_score)
What would the SQL look like to return all games where home_team_id or road_team_id is 1 and include the team_name of the opponent?
Not clearly stated in question, but I guess your main confusion is on how to get team_name from both home_team_id and road_team_id. You can do twice INNER JOIN for that purpose, for example :
select
g.*
, home.team_name as home_team_name
, road.team_name as road_team_name
from Games g
inner join Teams home on home.tid = g.home_team_id
inner join Teams road on road.tid = g.road_team_id
where g.home_team_id = 1
or g.road_team_id = 1

SQL, Struggling to believe HAVING can be more efficient than a join

I Am trying to find Players that have played in more than one game for a team in the following tables (** denotes private key), and find it hard to believe the best query I can come up with (below) is the most efficient. Ideas on how to improve it, and explanations as to why would be much appreciated (Trying to learn SQL)
Team (*tid*, name)
Game (*gid*, tid)
Player (*gid*, *name*)
SELECT Team_Name, Player_Name
FROM (SELECT GID, TID FROM GAME) G
,(SELECT NAME AS Player_Name, GID FROM PLAYER) P
,(SELECT NAME AS Team_Name, TID FROM TEAM) T
WHERE ( G.GID = P.GID
AND Player_Name IN (SELECT P.NAME
FROM GAME G
,PLAYER P
WHERE G.GID = P.GID
GROUP BY P.NAME
HAVING COUNT(P.NAME) > 1)
AND T.TID = G.TID
)
GROUP BY Team_Name, Player_Name
HAVING COUNT(Player_Name) > 1
ORDER BY Team_Name
You're asking which players have played in more than a single game.
SELECT P.Player_Name
FROM Player P
GROUP BY P.Player_Name
HAVING COUNT(DISTINCT P.GID) > 1
That will return all players who have played in more than 1 game (GID).
If you'd like to also GROUP BY team, then do this:
SELECT P.Player_Name, T.Team_Name
FROM Player P
JOIN Game G ON P.GID = G.GID
JOIN Team T ON G.TID = T.TID
GROUP BY P.Player_Name, T.Team_Name
HAVING COUNT(DISTINCT G.GID) > 1
It seems odd to have the GID in the Player table. Perhaps having a PlayerGames table would make more sense that stored the PlayerId and GameId -- better for database normalization. The Player table should only store a single record for each player.
Also, what is the real association between the player and the team. In this scenario, you're saying a player has to play a game, and a game has to have a team (or should a game have 2 or more teams). Let us know what you're going for, and we could help present your best option.
Good luck.

I need a SQL statement that returns the number rows in a table with a specific value

I'm sure this will equate down to the use of the COUNT statement but I'm not very good at SQL.
Here are my SQL Tables.
Teams Table:
TeamId TeamName RosterSpots
-----------------------------------------------
1 Miami Heat 12
2 New York Knicks 10
Players Table:
PlayerId PlayerName TeamId
------------------------------------
1 Dwyane Wade 1
2 Chris Bosh 1
3 LeBron James 1
4 Amar'e Stoudemire 2
What is the SQL (Miscroft SQL Server 2008) that will return the number of Players on each team?
output
Team Name PlayerCount
-----------------------------
Miami Heat 3
New York Knicks 1
I'd also like to return the RosterSpots and Team Id but really just the COUNT part above is what I'm puzzled with.
Use:
SELECT t.teamid,
t.teamname,
COALESCE(COUNT(p.playerid), 0) AS playercount,
t.rosterspots
FROM TEAMS t
LEFT JOIN PLAYERS p ON p.teamid = t.teamid
GROUP BY t.teamid, t.teamname, t.rosterspots
SELECT t.TeamID, RosterSpots, TeamName, COALESCE(COUNT(p.PlayerID),0)
FROM Teams t
LEFT JOIN Players p on t.TeamID = p.TeamID
GROUP BY TeamName,t.TeamID, RosterSpots
Should do the trick, but feel free to rename the count column to something more friendly.
Modify to a LEFT JOIN to allow for teams with no players