Condition with INNER JOIN gives wrong results - sql

I have the following tables
goal matches team_match
id | match_id | team_id | name match_id team_id | match_id | home_away
----------------------------- ----- ------------------------------
1 1 1 Ronaldo 1 1 1 home
2 1 2 Messi 2 1 away
3 1 2 Suarez 2 1 away
Now I want to get just players who played in the away team.
SELECT DISTINCT g.name
FROM goal g
INNER JOIN matches m
ON g.match_id = m.match_id
INNER JOIN team_match tm
ON tm.match_id = m.match_id
AND tm.home_away = 'away'
WHERE m.match_id = '1'
But instead of:
Messi
Suarez
I am getting:
Ronaldo
Messi
Suarez
It seams like my second INNER JOIN is totally ignored, even if I change from "home" to "away" I will get the same result.

The INNER JOIN is working correctly. Seems your database schema is the problem.
Why shouldn't Ronaldo be in the result set? You don't use the team_id anywhere. There is no information that Ronaldo was in the team that played home in the specified match.
A suggestion for a better schema:
Table teams
team_id
1
2
Table players:
playerid team_id name
1 1 Ronaldo
2 2 Messi
3 2 Suarez
Table matches
matchid hometeamid awayteamid
1 1 2
Table goals
matchid playerid
1 1
1 2
1 3
Then your query could look like this
SELECT p.Name FROM players p
INNER JOIN goals g ON (g.playerid = p.playerid)
INNER JOIN matches m ON (m.matchid = g.matchid AND m.awayteamid = p.team_id)
WHERE m.matchid = 1

You haven't proven that the first inner join is working either.
Try removing the blank lines

Related

How to make a view with 2 tables linked by another table?

I have 3 table
driver
id
first name
last_name
age
1
Joe
doe
26
2
John
smith
31
...
...
...
...
Location
id
name
zipcode
country
1
London
250 329
UK
2
NY
00501
USA
...
...
...
...
Travel
id
Person_id
location_id
nb_passenger
1
1
1
2
2
1
1
4
3
2
2
3
4
1
2
2
5
2
1
3
...
...
...
...
I'm looking to create a view to get the total number of passengers by destination and by driver, but it's taking the same row multiple times
I tried something like that but it didn't work
SELECT location.id AS location_id,
location.name AS location_name,
d.id AS driver_id,
d.name AS driver_name,
sum(tr.passenger) as passenger_count
FROM location
LEFT JOIN travel tr_0 ON location.id = tr_0.location_id
LEFT JOIN driver d ON tr_0.driver_id = d.id
LEFT JOIN travel tr ON location.id = tr.location_id AND tr.driver_id = d.id
GROUP BY location.id, location.name,...;
I'm sure it's simple but I'm not on the right way

SQL two table query

I have 2 tables:
Players
ID
Name
1
John
2
Maya
3
Carl
Results
ID
Player_ID
Result
1
1
250
2
1
300
3
2
100
4
2
350
5
3
500
I want to select all the names from the table Players and the top scores of each person.
What I have so far:
SELECT Players.Name, max(Results.Result)
FROM Players JOIN Results
WHERE Players.ID = Results.Player_ID
But this only selects
| Carl | 500 |
and I want
| John | 300 |
| Maya | 350 |
| Carl | 500 |
try with a condition on the result : it needs to be the highest (max) for the player ID.
Try this:
SELECT p.Name, r.result FROM Players p JOIN Results r WHERE p.ID = r.Player_ID and r.result = (select max(result) from results rr where rr.Player_ID = p.ID)
You need to GROUP BY Players.ID, Players.Name to your query. I added Players.ID in case two players have the same name:
SELECT Players.Name, max(Results.Result)
FROM Players JOIN Results
WHERE Players.ID = Results.Player_ID
GROUP BY Players.ID, Players.Name

Select from table 1 unless there is a relationship in 2 other tables

I need to query a name(s) from the Officials table, but exclude that name if the person has the day blocked.
For example, if Sam has blocked 8/21/2021 and 9/11/2021, he should not be selected if the corresponding dates are selected from the Games table. Sam should show up if 9/18/2021 is selected, however. I have 3 tables:
Officials tbl
RefId Name
---------------------
1 Jack
2 Sam
3 Jane
Games tbl Blocks tbl
GameId GameDate BlockId RefId BlockDate
------------------------- ----------------------
1 8/21/2021 1 2 8/21/2021
2 9/11/2021 2 2 9/11/2021
3 9/18/2021 3 3 8/21/2021
Desired Output
----------------------------------
If Game 1 is selected: Jack
If Game 2 is selected: Jack and Jane
If Game 3 is selected: Jack, Sam and Jane
The only 2 tables that are related are the Officials table and Blocks table, with the RefId. I need to compare the BlockDate of Blocks table to GameDate of Games table. I have tried some sql language and this below is obviously not correct, but I'm looking for a way to accomplish what I want to do:
#GameDate datetime,
Select c.Id, c.Name
From Officials c
Where In c.Id And Blocks.BlockDate <> Games.GameDate)
You can do it with NOT EXISTS:
SELECT o.*
FROM Officials o
WHERE NOT EXISTS (
SELECT 1
FROM Blocks b INNER JOIN Games g
ON g.GameDate = b.BlockDate
WHERE b.RefId = o.RefId AND g.GameId = ?
);
See the demo.

PostgreSQL - Selecting count of unique values in one and two columns

Firstly, I'd like to apologise for the ambiguous title (I promise to revise it once I'm actually aware of the problem I'm trying to solve!)
I have two tables, player and match, which look like the following:
player:
id name
-- ----
1 John
2 James
3 April
4 Jane
5 Katherine
match:
id winner loser
-- ------ -----
1 1 2
2 3 4
Records in the match table represent a match between two players, where the id column is generated by the database, and the values in the winner and loser columns reference the id column in the player table.
I want to run a query which spits out the following:
player.id player.name total_wins total_matches
--------- ----------- ---------- -------------
1 John 1 1
2 James 0 1
3 April 1 1
4 Jane 0 1
5 Katherine 0 0
I currently have a query which retrieves total_wins, but I'm not sure how to get the total_matches count on top of that.
select p.id, p.name, count(m.winner)
from player p left join match m on p.id = m.winner
group by p.id, p.name;
Thanks for your help!
Try
select p.id, p.name,
sum(case when m.winner = p.id then 1 end ) as total_wins,
count(m.id) as total_matches
from player p
left join match m on p.id in ( m.winner, m.loser )
group by p.id, p.name;
One method splits the match match table, so you have a single row for each win and loss. The rest is just a left join and aggregation:
select p.id, p.name, coalesce(sum(win), 0) as win, count(m.id) as total_matches
from player p left join
(select match, winner as id, 1 as win, 0 as loss from match
union all
select match, loser as id, 0 as win, 1 as loss from match
) m
on p.id = m.id
group by p.id, p.name;

Create 2 new columns from a query

I am battling with joins and inner joins.
I have 2 tables that look like this:
USERS
-----------------------------------------
ID | fname | lname | div_1_id | div_2_id
-----------------------------------------
1 paul smith 1 2
2 john lip 2 null
3 kim long 1 4
DIVISIONS
------------------
ID | name
------------------
1 estate
2 litigation
3 property
4 civil
DESIRED RESULT (sql query)
--------------------------------------------------
user.ID | fname | lname | div_1_name | div_2_name
--------------------------------------------------
1 paul smith estate litigation
2 john lip litigation
3 kim long estate civil
I would like to create a new table from a MS sql query that looks like the above.
Use LEFT JOIN for this:
SELECT u.ID, u.fname, u.lname
, d1.name as div_1_name
, d2.name as div_2_name
FROM USERS u
LEFT JOIN DIVISIONS d1 ON u.div_1_id = d1.ID
LEFT JOIN DIVISIONS d2 ON u.div_2_id = d2.ID
See this SQLFiddle
Try using sub-query:
select a.ID, a.fname, a.lname,
(select name from DIVISIONS b where b.id=a.div_1_id) div_1_name,
(select name from DIVISIONS b where b.id=a.div_2_id) div_2_name
from
USERS a
Use INNER JOIN
SELECT Users.ID, Users.fname, Users.lname, Divisions.name,Div.name
FROM Users INNER JOIN Divisions ON Users.div_id_1 = Divisions.ID
INNER JOIN Divisions Div ON Users.div_id_1 = Div.ID -- Second join with Divisions Table with Alias.