my heads hurt from trying to figure this out!
I have three tables
-Players
-Teams
-Games
Three junction tables with two columns.
-player_teams
-teams_games
-player_games
I need to list all Players who are in a Game (eg: Game_id = 111 from variable) that are not assigned a Team(in this game). i call them orphaned players
Basically get Teams that are in the game, get their Players and reverse match against Games_players. or the other way round i suppose.
i tried for two day no luck!
thanks!
/J
p.s after i posted this i got this far but it seems to complex!
SELECT * from players
JOIN
(SELECT DISTINCT games_players.player_id from games_players
Left JOIN
(Select team_players.player_id p1 from team_players
inner join (Select * from games_teams where games_teams.game_id = :P1) AS tm1 ON team_players.team_id = tm1.team_id) As f1
On games_players.player_id = f1.p1
where p1 is null) as q1
on players.player_id = q1.player_id
As the game is given, you can just look at the players in the game and the players of the teams in the game:
select *
from players
where player_id in
(
select player_id
from player_games
where game_id = 111
)
and player_id not in
(
select pt.player_id
from player_teams pt
join teams_games tg using (team_id)
where tg.game_id = 111
);
Related
I am struggling with the WHERE part of a query. The query itself contains a LEFT JOIN based on an ID that is present in both tables. However I require the where statement to only return the largest single result that is present in one of the columns. Currently I am return all the values in the join, including values that I do not want.
My Current SQL is
SELECT u.uid, t.id
GROUP_CONCAT(u.forename, ' ', u.surname) AS name,
GROUP CONCAT(DISTINCT scores.points) AS point
FROM users AS U
JOIN teamname AS t
LEFT JOIN (
SELECT team_id, id
FROM games AS g
LEFT JOIN (
SELECT points, team_id
FROM scores as s
) AS S ON t.id = S.team_id
WHERE IF (S.points > 3, S.points > 2, S.point =1)
) AS G ON t.id = G.team_id
ORDER BY surname ASC;
The result of such might be something along the lines of
NAME | TEAM | GAMES | POINTS
Joe | 1 | 1,2,3,4 | 1,3,3,2,3
In this instance the first game was a draw and was replied resulting in a higher points score, I am only wanting the higher points score based on that game.
Any help would be appreciated.
Updated with Tables
users
uid
forename
surname
Team
id
teamname
uid
games
id
team_id
points
Still not quite sure if I understood your tables correctly. It seems a users has one or more teams, each team has one or more games with one or more results per game. You want to show for each user and each team the games concatenated in one column and the highest points for each game concatenated in a second column.
If my assumptions are correct the following query should do the trick. Basically, you first group the data by user/team/game and select the max points per game, then you group the results by user/team and concatenate the games and points.
Please let me know if I misunderstood any of your requirements.
Example in an SQL Fiddle
SELECT
t.uid,
t.forename,
t.team_id,
GROUP_CONCAT(t.game_id) as games,
GROUP_CONCAT(t.max_points) as max_points
FROM (
SELECT
users.uid,
users.forename,
teams.id AS team_id,
games.id AS game_id,
max(games.points) as max_points
FROM
users
LEFT JOIN teams ON users.uid = teams.uid
LEFT JOIN games ON teams.id = games.team_id
GROUP BY
users.uid,
users.forename,
teams.id,
games.id
) t
GROUP BY
t.uid,
t.forename,
t.team_id
there are two models Player and Team which relates as Many-to-Many to each other, so schema contains three tables players, player_teams and teams.
Given that each team may consist from 1 or 2 two players, how to find a team by known player id(s)?
In this SQLFiddle http://sqlfiddle.com/#!15/27ac5
query for player ids 1 and 2 should return team with id 1
query for player id 2 should return teams with ids 1 and 2
query for player id 3 should return team with id 3
There's a mistake in the third bullet point of your problem statement, I think. There is no team 3. In that third case, I think you want to return team 2. (The only team that player 3 is on.)
This query requires 2 bits of information - the players you are interested in, and the number of players.
SELECT team_id, count(*)
FROM players_teams
WHERE player_id IN (1,2)
GROUP BY team_id
HAVING count(*) = 2
-- returns team 1
SELECT team_id, count(*)
FROM players_teams
WHERE player_id IN (2)
GROUP BY team_id
HAVING count(*) = 1
-- returns teams 1 & 2
SELECT team_id, count(*)
FROM players_teams
WHERE player_id IN (3)
GROUP BY team_id
HAVING count(*) = 1
-- returns team 2
edit: here's an example of using this via ruby, which maybe makes a little clearer how it works...
player_ids = [1,2]
sql = <<-EOF
SELECT team_id, count(*)
FROM players_teams
WHERE player_id IN (#{player_ids.join(',')})
GROUP BY team_id
HAVING count(*) = #{player_ids.size}
EOF
Is this what you are looking for?
select t.name
from teams t
inner join players_teams pt on t.id = pt.team_id
where pt.player_id = 1
-- "OK, SQL give me a team id where both of those two players played together"
select pt1.team_id
from players_teams pt1
inner join players_teams pt2 on pt1.team_id = pt2.team_id
where pt1.player_id = 1
and pt2.player_id = 2
This is a simple case of relational-division. We have assembled an arsenal of possible techniques here:
How to filter SQL results in a has-many-through relation
While the queries in the currently accepted answer should work, these queries should be shorter and faster for each of your examples:
SELECT team_id -- returns team 1
FROM player_teams pt1
JOIN player_teams pt2 USING (team_id)
WHERE pt1.player_id = 1
AND pt2.player_id = 2;
SELECT team_id -- returns team 1 and 2
FROM player_teams
WHERE player_id = 2;
SELECT team_id -- returns team 2 (and 3 in the improved fiddle)
FROM player_teams
WHERE player_id = 3;
There is simply no need for JOIN / GROUP BY / HAVING in cases 2 and 3.
If, however, you want to find teams that consist of player 3 only (and no other member), use this:
SELECT pt1.team_id -- returns team 3
FROM player_teams pt1
LEFT JOIN player_teams pt2 ON pt2.team_id = pt1.team_id
AND pt2.player_id <> pt1.player_id
WHERE pt1.player_id = 3
AND pt2.player_id IS NULL;
According to your definition this doesn't seem unlikely:
Given that each team may consist from 1 or 2 two players
Related:
Select rows which are not present in other table
SQL Fiddle with improved schema and extended test case.
Notably, I added FK constraints and replaced your UNIQUE index with a PRIMARY KEY constraint. More here:
How to implement a many-to-many relationship in PostgreSQL?
Universal query
To make the same query work for either two player_id or one player_id and NULL, use the NULL-safe comparison operator IS NOT DISTINCT FROM:
SELECT pt1.team_id -- returns team 3
FROM player_teams pt1
LEFT JOIN player_teams pt2 ON pt2.team_id = pt1.team_id
AND pt2.player_id <> pt1.player_id
WHERE pt1.player_id = 3
AND pt2.player_id IS NOT DISTINCT FROM 2;
I added both cases to the fiddle. Might be a bit slower overall, and definitely slower than the simple query for just one player_id.
you may try the code below:
DECLARE #player_id_to_search INT
SET #player_id_to_search = 1
SELECT DISTINCT teams.name
FROM teams
JOIN players_teams ON players_teams.team_id = teams.id
JOIN players ON players.id = players_teams.player_id
AND players.id = #player_id_to_search
I have three tables: Players, PlayersArchive, Races. The Players and PlayersArchive tables are exactly the same structure.
In Players and PlayersArchive we have PlayerID and Name.
In Races we have in one row:
RaceID, Record1PlayerID, Record2PlayerID, Record3PlayerID, Record4PlayerID and Record5PlayerID
The task is to SELECT the whole Races table, but instead of the player ID fields it should return their names.
e.g.:
Races table:
RaceID: 1
Record1PlayerID: 2
Record2PlayerID: 1
Record3PlayerID: 0
Record4PlayerID: 0
Record5PlayerID: 0
Players table:
PlayerID: 1
Name: Jhon
PlayersArchive table:
PlayerID: 2
Name: Jack
result:
1 Jack Jhon NULL NULL NULL
You have two problems with your data structure. The first is that you should have a separate table for the players in each race, with one row per player/race combination. Putting them in separate columns on a single row is a bad idea.
The second problem is putting the names in two different tables. From your question, I cannot tell if both the players table and playersarchive table are necessary. So, I'll assume the archive is not necessary.
The solution is to join from the races table to the table with the players information:
select r.*,
p1.name as name1,
p2.name as name2,
p3.name as name3,
p4.name as name4,
p5.name as name5
from races r left outer join
players p1
on r.record1playerid = p1.playerid left outer join
players p2
on r.record1playerid = p2.playerid left outer join
players p3
on r.record1playerid = p3.playerid left outer join
players p4
on r.record1playerid = p4.playerid left outer join
players p5
on r.record1playerid = p5.playerid left outer join
If the data is really in both Players and PlayersArchive, then players might need to be:
(select distinct playerid, name from ((select p.* from players) union all (select pa.* from playersarchive)) t) p1 . . .
This combines the two tables together for looking up the name.
This will only demonstrate a posible solution to what you ask.
Select RaceId, p1.Name AS Name1 From Races AS r
Left Join (
Select * From Players
Union Select * From PlayersArchive
) AS p1 On r.Record1PlayerID = p1.PlayerID;
You should repeat this left join 4 more times whithin your query to get all 5 names.
Please note that with big data this might take a long time to execute.
I have three tables:
players
------
id|name
teams
-------
id|name
teams_players
-------------
id|teamID|playerID
I now want to get every entry from table "players" where players.id is for example in the team with id 15. With other words: I want to get every player that belongs to a specific team (e.g teamID=15)
I tried a join but it fails.
Here is what i got so far:
"SELECT players.*
FROM players
JOIN teams_players
ON teams_players.teamID = 15
GROUP BY players.id";
You are way overcomplicating this.
select players.*
from players
join teams_players
on players.id = teams_players.playerid
where teams_players.teamid = 15
The JOIN part has nothing to do with the number 15. The 15 is how you filter the results.
you can join your table with more than one conditions also you haven't mention the relation between your tables in the on clause
SELECT players.*
FROM players
JOIN teams_players
ON (players.id = teams_players.playerid AND teams_players.teamID = 15 )
GROUP BY players.id
I have 2 tables like this:
[games]
gameid
hometeamid
awayteamid
score
and
[teams]
teamid
teamname
How would i create a query to output something like:
[home team][away team][score]
49ers chargers 28-17
You see, i need to resolve 2 team names with 2 team ids within the same table and output just the names. Thanks in advance for your help!
SELECT
ht.TeamName AS HomeTeam,
vt.TeamName AS AwayTeam,
g.Score
FROM
games g INNER JOIN teams ht
on g.hometeamid = ht.teamid
INNER JOIN teams vt
on g.awayteamid = vt.teamid
I'd suggest naming the tables "game" and "team" - as I'm not a fan of plural table names. I'm not alone in this opinion, but it's really a style/preference thing.
This should work for you:
select t1.teamname, t2.teamname, g.score
from games as g
left outer join team as home_team
on g.hometeamid = home_team.id
left outer join team as away_team
on g.awayteamid = away_team.id
SELECT (SELECT teams.teamname FROM teams WHERE teams.teamid=games.awayteamid) AS awayteam,
(SELECT teams.teamname FROM teams WHERE teams.teamid=games.hometeamId) AS hometeam, score
FROM games
WHERE gameid = '1'