How to shownicknames instead of foreign key in SQL - sql

So I'm practicing queries on SQL for educational purposes and I'm running queries from an NBA Basketball dataset. I want to make a query that will show me a date, home team, away team, and winner column. I can easily do this with this query:
SELECT game_id, SUBSTRING(date,0,11) AS Date_Only, team_id_home, team_id_away, team_id_winner
FROM game
However, these only show the id's of the teams. I don't want to see the foreign key id's of the teams, I want to see the nicknames for the teams which there's a separate table where the team id's and their nicknames are. How am I able to show the nicknames instead of the foreign keys? I've thought of a few things but there may be an easier way to do this. Appreciate the help.

The query needs to join the table that contains the nicknames so that you can select the appropriate column, e. g.
SELECT game_id, SUBSTRING(date,0,11) AS Date_Only,
home_team.nickname AS home_team_nickname,
away_team.nickname AS away_team_nickname,
winner_team.nickname AS winner_team_nickname
FROM game
INNER JOIN team home_team ON game.team_id_home = home_team.team_id
INNER JOIN team away_team ON game.team_id_away = away_team.team_id
INNER JOIN team winner_team ON game.team_id_winner = winner_team.team_id
;

Related

SQL - Distinct Not Providing Unique Results for Designated Column

I'm currently learning SQL by working through these exercises: https://sqlzoo.net/wiki/The_JOIN_operation
I'm on Example 8 which asks: "Show the name of all players who scored a goal against Germany."
Here is what I currently have:
SELECT DISTINCT(goal.player), goal.gtime, game.team1, game.team2
FROM game JOIN goal ON (goal.matchid = game.id)
WHERE (game.team1='GER' OR game.team2='GER') AND (goal.teamid<>'GER')
I would expect that results would be returned with only unique names. However, that is not the case as we can see "Mario Balotelli" is listed twice. Why doesn't the DISTINCT command work in this instance?
Thank you!
DISTINCT operates on the record level, so you should use distinct for the whole row or if you need extra fields to show up in your result, you need to perform a GROUP BY on the player and bring along other fields by joining to the grouped result.
but i reckon the intended answer is only the player name, so query would be something like this:
SELECT DISTINCT player
FROM game JOIN goal ON matchid = id
WHERE (game.team1='GER' OR game.team2='GER') AND (goal.teamid<>'GER')
It looks like "Mario Balotelli" can have multiple goal.gtime. Or can have different contributing values from Team1 and Team2. So try removing the additional columns you have in your select clause.
DISTINCT gets the distinct rows based on all selected columns. As the goal times differ selecting that column will make the rows different (distinct) from one another.
The question only asks you to select the player's name
SELECT DISTINCT player
FROM game
JOIN goal ON matchid = id
WHERE (team1='GER' OR team2='GER')
AND (teamid <>'GER')
This link looks like it would useful further reading https://www.designcise.com/web/tutorial/what-is-the-order-of-execution-of-an-sql-query
Edit: If you want more than one column but only a distinct list of players you are in the realms of aggregation, you would min/max/sum/avg the other data for the group.
SELECT player, team1, team2, MIN(gtime) AS min_gtime, MAX(gtime) AS max_gtime, COUNT(1) AS goals_scored
FROM game
JOIN goal ON matchid = id
WHERE (team1='GER' OR team2='GER')
AND (teamid <>'GER')
GROUP BY player, team1, team2

SQL: How can I select a value with associated value from my table?

I am trying to create a SQL SELECT that displays the player's username and the name of the team associated with the player. This is my code but it don't works like expected:
SELECT Player.userName AS Player,
Teams.TeamName AS [Team Name]
FROM Players, Teams
INNER JOIN Players
ON Team.ID = Player.userName
This is the Team's table
This is the player's table I just included the names only.
This is the full Player's Table with the contents of what is inside the table.
Your syntax is a bit off in your FROM clause. The best rule of thumb here is to NEVER use a comma in your FROM clause (the only exception is if you want to join EVERY row from one table to EVERY row of another creating a cartesian product of the two tables, but we rarely do that).
When you specify the relationship of the two tables in the ON clause of your JOIN you need to put the column(s) from each table that they have in common. A Team.ID will NEVER match to a Players.userName, so that is not the proper join condition.
Assuming you have a TeamID column in your players table so you know which Team each Player is on, you will have SQL that will look like:
SELECT Players.userName AS Player,
Teams.TeamName AS [Team Name]
FROM Teams
INNER JOIN Players
ON Team.ID = Players.[TeamName_]

SQL Trying to Outer Join Tables but not working

So, I've a Uni assignment and the lecturer has picked this week to be ill and unable to answer questions.
We've been given a baseball database made up of 4 tables to work with. Table structures are as follows:
TABLENAME:(column1, column2...etc) PK = Primary Key, FK = Foreign Key
PLAYER:(num PK, name, dob, team FK, position)
GAME:(num PK, gamedate, hometeam FK, awayteam FK, homescore,
awayscore)
GAMESTAT:(gamenum PK, playernum FK, homeruns, strikeout)
TEAM:(code PK, name, town, ground)
The aim of this particularly question is to obtain the name of the stadium's (ground in team table), the sum of the home runs scored on that ground, the sum of the strikeouts and then the sum of these two values within a specified date range.
My query and issue are below:
SELECT
t.ground AS GROUNDPLAYED,
SUM(gs.homeruns) as TOTALHOMERUNS,
SUM(gs.strikeouts) AS TOTALSTRIKEOUTS,
SUM(gs.homeruns + gs.strikeouts) AS COMBINEDTOTAL
FROM team t
LEFT OUTER JOIN game g ON g.hometeam = t.code
LEFT OUTER JOIN gamestat gs ON g.num = gs.gamenum
WHERE g.gamedate BETWEEN '7-AUG-2014' AND '13-AUG-2014'
GROUP BY t.ground;
My problem lies in the fact that I get the correct values for games played but regardless of using the LEFT OUTER JOIN, I'm not getting all the stadium's to list. I'm convinced it has to do with the fact that I have had to join to the hometeam from the GAME table and it can only pick the home stadiums based on that.
Any help you may be able to offer would be much appreciated.
Move your WHERE clause to the ON clause for the join to gamestat.
By imposing the filter criteria in the WHERE clause, it occurs after the join has been performed, removing the stadiums with no activity. Once this predicate is moved to the appropriate ON clause it will filter the gamestat's before the join instead of after.
You have experienced the good fortune to encounter this important quirk of SQL, that the positioning of predicates affects the result-set, early in your education.

sqlite Joins with MAX

I have 2 tables. One displays a game played (Date,Where, result,opponent etc) and the other one the details of a batting innings (runs scored, etc) Both tables have a primary key that relates the batting back to a specific game.
I am trying to return the OPPONENT column from Games when the MAX (highest) score is recorded in the table BATTING, but currently i am unsure how to do this.
The 2 tables can be found here
http://i.imgur.com/bqiyD3X.png
The example from these tables would be (max score is 101 in RUNSSCORED, so return the linked OPPONENT from GAMEINDEX which is "Ferndale"
Any help would be great. Thanks.
Is this what you are looking for?
select OPPONENT
from GAMES
where GAMESINDEX in
(select GAMESINDEX from BATTING order by RUNSSCORED desc limit 1);
If there isn't a unique max RUNSSCORED value, then the answer might not be deterministic.
If you want multiple winners in that case, you could use
select OPPONENT
from GAMES natural join BATTING
WHERE RUNSSCORED in (select MAX(RUNSSCORED) from BATTING);
SELECT G.OPPONENT, MAX(B.RUNSSCORED)
FROM GAMES AS G
INNER JOIN BATTING AS B
ON G.GAMESINDEX = B.GAMESINDEX

SQL Database Design Many to Many

I am creating a database based on a sporting game to store matches and each player involved in each match. I am having trouble resolving a many to many relationship. I currently have the following tables:
Player
id
name
Match
id
date
PlayerMatch
player_id
match_id
home_team
goals_for
goals_against
There will always be a minimum of two players in a match. Is this the best design for this approach?
I would recommend a sticking with a many to many relationship. This allows you to change the specifications of how many players you can have in a game easily while not complicating the data model much.
Player
id
name
Match
id
date
PlayerMatch
player_id
match_id
is_home
goals_for
goals_against
Foreign key from PlayerMatch to Player
Foreign key from PlayerMatch to Match
--All the matches a player has played in.
SELECT m.*
FROM Player p
JOIN PlayerMatch pm
ON p.id = pm.player_id
JOIN Match m
ON m.id = pm.match_id
WHERE p.id = /*your player Id*/
--All the players in a match
SELECT p.*
FROM Match m
JOIN PlayerMatch pm
ON m.id = pm.match_id
JOIN Player p
ON p.id = pm.player_id
WHERE m.id = /*your match Id*/
--player information for a single match.
SELECT pm.*
FROM Player p
JOIN PlayerMatch pm
ON p.id = pm.player_id
JOIN Match m
ON m.id = pm.match_id
WHERE p.id = /*your player Id*/
AND m.id = /*your match Id*/
That is a valid option, though I would suggest a naming convention where you use the same column name in both tables (i.e. use match_id in both Match and PlayerMatch; same for player_id). This helps make your SQL a bit more clear and when doing joins in some databases (MySQL) you can then use the 'using (col1, col2, ...)' syntax for the joins.
I wouldn't use the many-to-many relationship, I would do like this:
Player
id
name
Match
id
home_player_id
guest_player_id
date
goals_home_player
goals_guest_player
I think I'd try to model the match first & then see what happens with the table design :
Match
-------------
match_Id
player1_Id
player2_Id
player1_Goals
player2_Goals
Where player1_Id and Player2_Id are both foreign keys onto the Player table
Player
---------
Id
Name
By convention player1 would always be the home team
then you would query it like
Select p1.name as player1_Home, p2.name as player2_away,
matchId,
player1_Goals as homeGoals, player2_Goals as awayGoals
from Match m
inner join Player p1 on p1.id = m.Player1_Id
inner join Player p2 on p2.id = m.Player2_Id
This sort of data relationship is not at all unnatural. To set it up, just ask yourself two questions:
Do players have more than one match?
Do matches have more than one player?
If the answer is yes to both, then you have a many-to-many relationship and these are not at all uncommon. Their implementation is only slightly more complicated. In a one-to-many relationship, you'd hold a foreign key to a list of records in some table. As it happens, this is still how it works in many-to-many relationships, except that both the Players and the Matches table will need a foreign key to some list of records.
This list is called the Bridge Table. So you'll need to use a total of three tables to descrive the relationship
Players
-------
player_id
<player attribute columns, eg last_name, first_name, goals_scored, etc.>
Player_Match
------------
player_id
match_id
Matches
-------
match_id
<a list of columns that are match attributes, eg. match date, etc.>
The table in the middle of the diagram above is called a bridge table, and it does nothing more than map players to matches, and it also maps matches to a list of players. Often, bridge tables have only 2 columns, each representing a foreign key to one of the bridged tables. There is no need for a primary key in a bridge table, and if there is not one, it means that a player can have more than one of the same match. If a player can have only one of one kind of match, then make the primary key for each row of the bridge table a composite key on both of the columns.
In database design, normalization is a highly desirable relational goal because it provides a database with the greatest possible flexibility and the lowest amount of redundancy. To normalize, ask yourself if the data you want to put in a table is -really- an actual attribute of the object described by the primary key. For example, is the home_team an actual attribute of the match. I would say no, it is not. In this case, you should replace home_team in your PlayerMatch table with a foreign key to a Teams table. In your Matches table, you ought to have two columns. One for a home team foreign key, and one for the away team key. The teams are not actual attributes of a match and so to normalize the Match table, you'd want to put those data in tables of their own.
Agree with M Hagopian, the op schema looks like a good start.