How to inner join same column - sql

Sorry for the confusing title, I don't really know how to word it. so what I'm trying to achieve is to define two different column data into one id. so teamID has the team ids, and I'm trying to define both the home ids and away ids on the same inner join, but don't know the proper script
SELECT *
FROM fixtures INNER JOIN
teams
ON fixtures.homeTeam = teams.teamID INNER JOIN
teams
ON fixtures.awayTeam = teams.teamID;
what I want to achieve is basically teamaway= teamID and homeaway = teamID and then TeamID = teamName

You need table aliases:
SELECT f.*, th.*, ta.*
FROM fixtures f INNER JOIN
teams th
ON f.homeTeam = th.teamID INNER JOIN
teams ta
ON f.awayTeam = ta.teamID;
Note . . . You should select the column that you want explicitly and give them meaningful names. For instance:
SELECT f.*, th.name as home_team, ta.name as away_team
FROM fixtures f INNER JOIN
teams th
ON f.homeTeam = th.teamID INNER JOIN
teams ta
ON f.awayTeam = ta.teamID;
Otherwise, you'll have duplicate column names which are a bit hard to understand.

Related

SQL Query using multiple JOINS without sub query

Lets say I have three tables with these columns,
Players - id, name
Events - id, name
Games - first_player_id, second_player_id, event_id.
And I need the players details who are playing in a game which is happening in an event.
And I could write query like,
SELECT players.id, events.id as event_id,
(SELECT name as player_one_name from players where id = games.first_player_id),
(SELECT name as player_two_name from players where id = games.second_player_id),
games.id as game_id
FROM events
INNER JOIN games on events.id = games.event_id
INNER JOIN players on games.first_player_id = players.id;"
Here I am using two sub queries to fetch players name. And it gives correct results. Can this query be optimized? For ex, can I remove any subquery or innerjoin ?
FYI, I use PostgreSQL database.
Thanks.
If you do not want sub queries in your select statement then you must provide a join for each subset. Since your database is set oriented the two INNER JOINS would prove more efficient.
SELECT players.id, events.id as event_id,
player_one_name=player_one.name,
player_tow_name=player_two.name
FROM events
INNER JOIN games on events.id = games.event_id
INNER JOIN players player_one on games.first_player_id = player_one.id
INNER JOIN players player_two on games.second_player_id = player_two.id
You must do a join for each foreign key
SELECT players_a.id, events.id as event_id,
players_a.name as player_one_name,
players_b.name as player_two_name,
games.id as game_id
FROM events
INNER JOIN games on events.id = games.event_id
INNER JOIN players players_a on games.first_player_id = players.id
INNER JOIN players players_b on games.first_player_id = players.id
The currently accepted answer is right about joining the players table twice, but mostly wrong otherwise. This would work:
SELECT e.id AS event_id
,g.id AS game.id
,p1.name AS first_player
,p2.name AS second_player
FROM events e
LEFT JOIN games g ON g.event_id = e.id
LEFT JOIN players p1 ON p1.id = g.first_player_id
LEFT JOIN players p2 ON p2.id = g.second_player_id;
Use LEFT [OUTER] JOIN to cover the cases where an event does not have a game or a game does not have both players (yet).
Use table aliases to simplify your syntax. To join the same table twice you also need at least one table alias.
After attaching an alias to a table in the FROM list, only that alias is visible in your query, not the original name of the table.
Study the manual for details.

Select Query from 3 tables with foreign keys

I Have 3 Tables with foreign keys to each other.
I want to write a SQL Server Stored Procedure to select records from one of them.
Now, let's suppose that i want all the Winner records referring to the Player records referring to The Game with the ID=2, how can i proceed?
Thank you.
you have specified all the Winner records So that i have used the left join for player and game. But the Overall code works according to the where condition.
Try This,
select w.* from Winner w
left Join Player p on p.ID_player = w.player_FK
left join Game g on g.ID_game = p.Game_FK
where Game.ID_game = 2
You need to use a SELECT and INNER JOIN then to filter on GameID 2 you can use a WHERE clause.
SELECT ID_Winner, Name, Lastname, Player_FK
FROM Winner
INNER JOIN Player on Player.ID_Pplayer = Winner.Player_FK
INNER JOIN Game ON Game.ID_game = Player.Game_FK
WHERE Game.ID_game = 2

Getting individual counts of a tables column after joining other tables

I'm having problems getting an accurate count of a column after joining others. When a column is joined I would still like to have a DISTINCT count of the table that it is being joined on.
A restaurant has multiple meals, meals have multiple food groups, food groups have multiple ingredients.
Through the restaurants id I want to be able to calculate how many of meals, food groups, and ingrediants the restaurant has.
When I join the food_groups the count for meals increases as well (I understand this is natural behavior I just don't understand how to get what I need due to it.) I have tried DISTINCT and other things I have found, but nothing seems to do the trick. I would like to keep this to one query rather than splitting it up into multiple ones.
SELECT
COUNT(meals.id) AS countMeals,
COUNT(food_groups.id) AS countGroups,
COUNT(ingrediants.id) AS countIngrediants
FROM
restaurants
INNER JOIN
meals ON restaurants.id = meals.restaurant_id
INNER JOIN
food_groups ON meals.id = food_groups.meal_id
INNER JOIN
ingrediants ON food_groups.id = ingrediants.food_group_id
WHERE
restaurants.id='43'
GROUP BY
restaurants.id
Thanks!
The DISTINCT goes inside the count
SELECT
COUNT(DISTINCT meals.id) AS countMeals,
COUNT(DISTINCT food_groups.id) AS countGroups,
COUNT(DISTINCT ingrediants.id) AS countIngrediants
FROM
restaurants
INNER JOIN
meals ON restaurants.id = meals.restaurant_id
INNER JOIN
food_groups ON meals.id = food_groups.meal_id
INNER JOIN
ingrediants ON food_groups.id = ingrediants.food_group_id
WHERE
restaurants.id='43'
GROUP BY
restaurants.id
You're going to have to do subqueries, I think. Something like:
SELECT
(SELECT COUNT(1) FROM meals m WHERE m.restaurant_id = r.id) AS countMeals,
(SELECT COUNT(1) FROM food_groups fg WHERE fg.meal_id = m.id) AS countGroups,
(SELECT COUNT(1) FROM ingrediants i WHERE i.food_group_id = fg.id) AS countGroups
FROM restaurants r
Where were you putting your DISTINCT and on which columns? When using COUNT() you need to do the distinct inside the parentheses and you need to do it over a single column that is distinct for what you're trying to count. For example:
SELECT
COUNT(DISTINCT M.id) AS count_meals,
COUNT(DISTINCT FG.id) AS count_food_groups,
COUNT(DISTINCT I.id) AS count_ingredients
FROM
Restaurants R
INNER JOIN Meals M ON M.restaurant_id = R.id
INNER JOIN Food_Groups FG ON FG.meal_id = M.id
INNER JOIN Ingredients I ON I.food_group_id = FG.id
WHERE
R.id='43'
Since you're selecting for a single restaurant, you shouldn't need the GROUP BY. Also, unless this is in a non-English language, I think you misspelled ingredients.

Need help with a simple Join

Oi
Right to the problem.
SELECT *,t.id AS threadid FROM threads t
LEFT JOIN players p on p.id = t.last_poster
WHERE t.boardid = $boardid
I have two fields in threads called posterid and lastposterid. Which are the IDs of the thread starter / last poster. What I want to do is to get their names from players table.
But how?
You just need to join to your players table twice, like this.
SELECT
threads.*,
starterPlayer.*,
lastPosterPlayer.*
FROM
threads
LEFT OUTER JOIN
players starterPlayer
ON
starterPlayer.id = threads.posterid
LEFT OUTER JOIN
players lastPosterPlayer
ON
lastPosterPlayer.id = threads.lastposterid
You can join to the same table twice and give the table a different alias.
This presumes that there always will be a first and last poster, if this is the case then you want an INNER JOIN rather than a LEFT JOIN, you will need to change the select statement to get the relevant fields.
SELECT t.id AS threadid, playerFirst.name AS FirstPoster, playerLast.name as LastPoster
FROM threads t
INNER JOIN
players playerFirst ON playerFirst.id = t.posterid
INNER JOIN
players playerLast ON playerLast.id = t.lastposterid
How about...
SELECT *,
(SELECT name
FROM players
WHERE players.id = threads.posterid) AS poster,
(SELECT name
FROM players
WHERE players.id = threads.lastposterid) AS last_poster
FROM threads;

SQL join over five tables

I have five tables:
models: id, name, specification
models_networks: id, model_id, network_id
networks: id, name, description
countries_networks: id, country_id, network_id
countries: id, countryName, etc, etc
the models table is connected to the networks table via models_networks with a many to many relation.
the networks table is connected to the countries table via countries_networks with a many to many relation
I need to do the following query, but I'm stuck:
Select all the models that will work in a specific country.
e.g.: say France has two networks. PigNetwork and CowNetwork. I want to get all the models that work on PigNetwork or CowNetwork, basically any that work in that country one way or the other.
If I've made myself clear, can someone help with the JOIN query please? I've only ever gone as far as joining two tables before. Thanks.
SELECT
m.name AS model_name,
c.countryName,
COUNT(*) AS network_count
FROM
models AS m
INNER JOIN models_networks AS mn ON mn.model_id = m.id
INNER JOIN networks AS n ON n.id = mn.network_id
INNER JOIN countries_networks AS cn ON cn.network_id = n.id
INNER JOIN countries AS c ON c.id = cn.country_id
WHERE
c.countryName = 'France'
GROUP BY
m.name,
c.countryName
Something along the lines of this should work...
SELECT M.Name As ModelName FROM Countries C
INNER JOIN Countries_Networks CN
ON C.CountryId = CN.CountryId
INNER JOIN Networks N
ON CN.NetworkId = N.NetworkId
INNER JOIN ModelNetworks MN
ON MN.NetworkId = N.NetworkId
INNER JOIN Model M
ON M.ModelId = MN.ModelId
WHERE C.CountryName = 'FRANCE'
SELECT m.id
FROM model m
WHERE EXISTS
(
SELECT NULL
FROM model_networks mn
JOIN countries_networks cn
ON cn.network_id = mn.network_id
AND cn.country_id = #code_of_france
WHERE mn.model_id = m.id
)
This is efficient since it returns a model right that moment it finds the first suitable network.
Make sure you have the following UNIQUE indexes:
model_networks (model_id, network_id)
country_network (country_id, network_id)
SELECT models.id, models.name, models.specifications JOIN models_networks ON models.id=models_networks.model_id WHERE models_networks.networks_id IN (1,2)
(replace 1,2 with your network ids )
Doesn't look like you need two joins if you just want the models. You only need more joins if you don't know the network ids or if you need columns out of the other tables. The syntax for that is the same though. You just start with JOIN <table> ON <field>=<field> before the WHERE statement
select models.id, models.name, models.specification from models inner join models_networks on models.id = models_network.network_id inner join countries_networks on models_network.network_id = countries_networks.network_id where countries_networks.countryName = 'France'