SQL - Left join 2 foreign keys to 1 primary key - sql

I have two tables, Games and Teams. What should my sql statement look like to make a list of games that pulls in the TeamName that is linked to the TeamID1 and TeamID2 fields? I believe I could use a left join but I'm not sure what to do with two foreign keys that link to one primary key. Thank you very much for any help you could provide.
Games
GameID
TeamID1
TeamID2
Result
Teams
TeamID
TeamName

I often see folks struggle with the idea of joining a table unto itself or multiple times in the same query (as it were here). Once mastered, it's a great technique to use on tables that have a lot of relationships between rows (such as a list of teams that have to play each other!). As others have pointed out, you need to use two inner joins to accomplish this:
select
*
from
games g
inner join teams t1 on
g.teamid1 = t1.teamid
inner join teams t2 on
g.teamid2 = t2.teamid
So, if your games table looks like this:
GameID TeamID1 TeamID2
----------------------------
1 1 3
2 4 2
3 2 1
You will get the result set of:
g.GameID g.TeamID1 g.TeamID2 t1.TeamID t1.Name t2.TeamID t2.Name
----------------------------------------------------------------------------------
1 1 3 1 Lions 3 Bears
2 4 2 4 Oh My 2 Tigers
3 2 1 2 Tigers 1 Lions
Of course, I would alias these columns in the select statement, if I were me, for usability's sake:
select
g.GameID,
t1.Name as Team1,
t2.Name as Team2
from
...
This way, columns can be named appropriately, instead of having the t1 and t2 columns share the same names.
Now, to address the confusion about what a left join is. You see, a left join will take all of the rows from the first (or left) table, and then match up any rows on the join condition to the second (or right) table. For any rows from the left table, you will get null in all of the columns on the right table.
Delving into an example, let's say that somebody put in a null for TeamID2 on one of the rows for whatever reason. Let's also say that a team of TeamID 4 used to exist, but doesn't any more.
GameID TeamID1 TeamID2
----------------------------
1 1 3
2 4 2
3 1 null
Now, let's take a look at what a left join would be in terms of the query:
select
*
from
games g
left join teams t1 on
g.teamid1 = t1.teamid
left join teams t2 on
g.teamid2 = t2.teamid
Logically, this will grab all of our games, and then match them up to the respective teams. However, if a TeamID doesn't exist, we'll get nulls. It will look like so:
g.GameID g.TeamID1 g.TeamID2 t1.TeamID t1.Name t2.TeamID t2.Name
----------------------------------------------------------------------------------
1 1 3 1 Lions 3 Bears
2 4 2 null null 2 Tigers
3 1 null 1 Lions null null
Therefore, a left join will only be necessary if a team is optional.
In your case, you'll be using an inner join to join a table multiple times. This is a very common practice and is rather useful. It avoids some of the pitfalls of subqueries (especially on MySQL), while allowing you to grab data from the table for intratable comparisons. This is markedly useful when trying to find the order of something, or related rows.
Anyway, I hope this very rambling answer helps out somebody somewhere.

SELECT *
FROM Games G
INNER JOIN Teams T1
ON G.TeamID1 = T1.TeamID
INNER JOIN Teams T2
ON G.TeamID2 = T2.TeamID

I don't think you'll need a left outer join unless one of the two teams in a game is optional. Logically to me it seems that both would be required, so your query would look like this:
SELECT *
FROM Games AS G
INNER JOIN Teams AS T1 ON T1.TeamID = G.TeamID1
INNER JOIN Teams AS T2 ON T2.TeamID = G.TeamID2

If TeamID1 and TeamID2 are NOT NULL, then you want to use an INNER JOIN, otherwise you could use a LEFT JOIN.

You need to use alias:
SELECT GameID, team1.TeamName, team2.TeamName
FROM Games INNER JOIN teams team1 ON (Games.TeamID1 = team1.TeamID)
INNER JOIN teams team2 ON (Games.TeamID2 = team2.TeamID)

Related

Efficient way to join multiple columns to the same column? - SQL

I have a bunch of tables combined together, which each have a column containing some form of user_id. This leads to 12 user_id columns in total.
I want to join each of these user_id columns with a user_id column in a mapping table in order to retrieve the username for each of these user ids.
So (assuming I have 5 user id columns),
Input:
My Combined Tables Result:
t1.user_id t2.user_id t3.user_id t4.user_id t5.user_id
1 2 3 4 5
Mapping Table:
user_id username
1 A
2 B
3 C
4 D
5 E
Output:
t1.username t2.username t3.username t4.username t5.usernamne
A B C D E
My code looks something like:
SELECT m1.username, m2.username, m3.username, m4.username, m5.username
FROM {join logic for 5 tables here}
JOIN mapping m1
ON t1.user_id = m1.user_id
JOIN mapping m2
ON t2.user_id = m2.user_id
JOIN mapping m3
ON t3.user_id = m3.user_id
JOIN mapping m4
ON t4.user_id = m4.user_id
JOIN mapping m5
ON t5.user_id = m5.user_id
I'm realizing this is extremely inefficient, especially for 12 columns which would mean 12 JOINs. Is there a better or faster way to do this? Thanks!
You might find it easier to use a correlated subquery for each username, especially where you have to implement many columns as it's easier to cut n paste!
Something like:
select
(select Username from Mapping m where m.UserId = t.UserId1) Username1,
(select Username from Mapping m where m.UserId = t.UserId2) Username2,
(select Username from Mapping m where m.UserId = t.UserId3) Username3 etc
from InputTable t

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 Multiple columns on one table joined column from other table

I've been trying to run an SQL query but haven't been having much luck. No matter what I do I can't seem to get it to run the way I need it to. I am able to get the tables to join and get the names across, but I can't get the query output I'm looking for.
I have two tables, one table has 3 columns for 1st, 2nd, and 3rd gate techs to be entered. The second table has a list of gate techs we use, the ID for the techs is the primary key.
What I'm looking for is an SQL statement that will get the the keys from the gate table. Example would be Gate Table ID 2 would get 2, 2, 1, then join with the tech table and return the tech names instead of the key.
I can one to work if I do the following, but cant get 3 separate columns with the data.
SELECT TName
FROM TechTable
INNER JOIN GateTable
ON GateTabe.Gate1=TechTable.ID
WHERE ID = 3
-
GateTable
ID Gate1 Gate2 Gate3
1 1 2 3
2 2 2 1
3 4 2 1
-
TechTable
ID TName
1 Tech1
2 Tech2
3 Tech3
4 Tech4
Query Result
ID Gate1 Gate2 Gate3
1 Tech1 Tech2 Tech3
2 Tech2 Tech2 Tech1
3 Tech4 Tech2 Tech1
join the techTable thrice, once for each different gate.
SELECT g.id,t1.TName as gate1,t2.TName as gate2,t3.TName as gate3
FROM GateTable g
INNER JOIN TechTable t1 ON g.Gate1=t1.ID
INNER JOIN TechTable t2 ON g.Gate2=t2.ID
INNER JOIN TechTable t3 ON g.Gate3=t3.ID
SELECT gt.ID, t1.TName as Gate1, t2.TName as Gate2, t3.TName as Gate3
FROM GateTable gt
LEFT JOIN TechTable t1
ON gt.Gate1=t1.ID
LEFT JOIN TechTable t2
ON gt.Gate2=t2.ID
LEFT JOIN TechTable t3
ON gt.Gate3=t3.ID
You can use INNER JOIN too but it gives you only mapped columns. In your example you specified Gate1 value as 4, but it is not there in TechTable. In this case, INNER JOIN skips that value. But LEFT JOIN would give you mapped values and null for the not available mapping.
You can use where clause if you need specific GateID.

Double inner join with 3 tables

Update years later:
I came back to answer my own question. I had no idea what an inner join was and apparently completely misused the term here.
I currently have the following 3 tables:
Team
TeamID
Player
PlayerID | TeamID
Match
Player1 | Player2 | Round
I want to write a query showing a match like:
Team1 | Team2
I figured out how to join my tables player and match, so far that works too, but I can't figure out how to replace the player name with the team name. Any idea? I have the following:
SELECT P1.PlayerID AS Player1, P2.PlayerID AS Player2
FROM MATCH
INNER JOIN PLAYER AS P1 ON MATCH.Player1 = P1.PlayerID
INNER JOIN PLAYER AS P2 ON MATCH.Player2 = P2.PlayerID
I've come back to this question years later.
Assuming the following tables:
Team
id | name
Player
id | team_id
Match
player1_id | player2_id | round
The result I wanted was something like
player1's team name | player2's team name | round
I used distinct originally, but distinct is not the correct way to remove duplicates, as Turophile correctly points out.
A better query would be something like
select t1.name, t2.name, m.round
from match as m
left join player as p1 on m.player1_id = p1.id
left join team as t1 on p1.team_id = t1.id
left join player as p2 on m.player2_id = p2.id
left join team as t2 on p2.team_id = t2.id

Query on table joined with itself

Today I have a final Exam. I approved, happily :D but one of the problems is really blowing my mind.
I need help, so I can rest in peace.
THE PROBLEM
We have a table "People"
(PK)id | name | fatherID
---------------------
1 | gon | 2
2 | cesar| 6
3 | luz | 2
4 | maria| 5
5 | diego| 6
6 | john | -
this is only an example of data.
This table has a relation with itself, on table fatherId(FK) with table id(PK)
I need to do a query that show me 2 columns, in one the name of a person, and in the another one, his/her cousin.
Pretty simple until here, right?
The problem is that I have some restrictions
ONLY ANSI allowed. NO T-sql, or another one. Also, ANSI 99 standard, not 2003 or higher
subquerys are not allowed. And the worst:
NO relations repeated.
For example, considering in this example, gon and maria are cousins.
If I show, gon | maria in the results, I can't show maria | gon.
SO, how I can do this?
Is really burning my head.
What I tried?
Well, the big problem was in the last requisite, the repetition of data. Ignoring that, I put this on my exam (knowing is wrong..)
select p3.name as OnePerson, p4.name as Cousin
from
people p1
inner join people p2 on p1.fatherid = p2.fatherid and p1.id != p2.id
inner join people p3 on p1.id = p3.fatherid
inner join people p4 on p1.id = p4.fatherid
of course, this is not solving the last requeriment, and I have a 4 in the test(we pass with 4) but anyway, my head is burning. So please, help me!
Another options explored
one of my friends, that also had the same exam said me
"Well, considering every relation is duplicated, I can use top
count(*) and an order by and get the half correct"
but.. Top is not ANSI!
You can add to your query WHERE p3.id < p4.id. This will eliminate duplicate results like gon | maria and maria | gon.
SELECT T1.id , T2.id FROM
(
SELECT A.id,A.fid FROM family A
WHERE a.fid IN
(
SELECT id FROM family
WHERE fid IN (SELECT id FROM family WHERE fid IS NULL)
)
)T1
JOIN
(
SELECT A.id,A.fid FROM family A
WHERE a.fid IN
(
SELECT id FROM family
WHERE fid IN (SELECT id FROM family WHERE fid IS NULL)
)
)T2
ON t1.fid<>t2.fid
AND t1.id<t2.id
This will give you the results in format you want.
SELECT TAB1.ID,TAB2.ID
FROM
(
SELECT * FROM people T1
WHERE fatherID IN ( SEL T1.ID FROM people T1 INNER JOIN people T2
ON( T1.id=T2.fatherID) WHERE T1.fatherID IS NOT NULL GROUP BY 1) ) TAB1
INNER JOIN
(
SELECT * FROM people T1
WHERE fatherID IN ( SEL T1.ID FROM people T1 INNER JOIN people T2
ON( T1.id=T2.fatherID)WHERE T1.fatherID IS NOT NULL GROUP BY 1) ) TAB2
ON( TAB1.fatherID<>TAB2.fatherID)
GROUP BY 1,2
WHERE TAB1.ID <TAB2.ID;