I have four tables like this:
**USERS**
___________________________
user_ID username password
---------------------------
1 user1 1234
2 user2 5678
**TEAMS**
______________________________________
team_ID formation team_name user_ID
--------------------------------------
1 4-4-2 team1 1
2 4-3-3 team2 2
**PLAYERS**
____________________________________
player_ID name position rating
------------------------------------
1 Ronaldo LW 94
2 Messi RW 93
3 Hazard LW 90
**ACTIVE PLAYERS**
___________________________________
ID player_ID team_ID cardview_ID
-----------------------------------
1 1 2 9
2 3 1 7
3 2 1 3
Each user has a team with a formation and a team name. The "active players" tables references the player_ID with the team_ID to see which players are currently active on which teams.
Let's say that user1 logs in to the application, then I want to get all the players name, ratingand their cardview_ID. Something that should look like this:
_____________________________
name rating cardview_ID
-----------------------------
Hazard 90 7
Messi 94 3
These are the players that are currently active on user1's team which is team1.
How can I get this joined table? I have tried with an inner join but that didn't seem to do the work for me.
_______________________________ EDIT_____________________________________
This is the query that doesn't give the desired result:
SELECT players.name, players.rating, activeplayers.cardview_ID
FROM players
INNER JOIN
activeplayers
ON players.player_ID = usedplayers.player_ID
I also tried to join them on team_ID.
Assuming you have the logged in user's ID available, I think this will give you what you're asking for:
SELECT
[PLAYERS].name,
[PLAYERS].rating,
[ACTIVE PLAYERS].cardview_ID
FROM [TEAMS]
JOIN [ACTIVE PLAYERS]
ON [TEAMS].team_ID = [ACTIVE PLAYERS].team_id
JOIN [PLAYERS]
ON [PLAYERS].player_id = [ACTIVE PLAYERS].player_id
WHERE [TEAMS].user_id = <logged_in_user_id>
Please also note the questions asking for clarifying details, and also feel free to respond if this query gets you part of the way but you need more information. The content in angle brackets are of course a placeholder. I also don't know your exact table names so you may need to replace what is in the square brackets with the actual table names.
Assuming that the query in your post contains a typo and is actually this:
SELECT players.name, players.rating, activeplayers.cardview_ID
FROM players
INNER JOIN
activeplayers
ON players.player_ID = activeplayers.player_ID
This query will correctly return all the players who are active players. Now to limit it only to the team for User1, you need to add an additional join to the Teams table, same way you did the join above, and then add a WHERE clause that filters on the Teams.UserID.
That's it.
Related
So I've got these three tables (it's a table tennis game):
table1: (goals, a user made, multiple rows)
id_goal
sp_id
game_id
time
table2: (users, multiple rows)
id_user
username
info_text
table3: (users_in_a_game, multiple rows)
id_uiag
game_id
sp_id
Now, I want to get all users from users_in_a_game, that played a game, want the name from users and the COUNT(goals) for every player, but the COUNT of the goals not in SUM, but for every single match in the specific row. So the result would be:
game1 - user1 - 50 goals
game1 - user2 - 20 goals
game2 - user3 - 12 goals
game2 - user1 - 7 goals
...
So far, I've coded this code:
SELECT *, COUNT(goals.sp_id) AS goals_per_game
FROM users_in_a_game
LEFT JOIN goals ON users_in_a_game.game_id = goals.game_id
GROUP BY goals.sp_id;
The problem is, that if a player was participating in the game, but doesn't score a goal, he doesn't get listed AT ALL. So how can I fix that?
Thank you in advance.
I think you want to aggregate by the user id and game id. I think:
SELECT ug.id_uiag, ug.game_id, COUNT(g.sp_id) AS goals_per_game
FROM users_in_a_game ug LEFT JOIN
goals g
ON ug.game_id = g.game_id
GROUP BY ug.id_uiag, ug.game_id;
I am not entirely sure even how to name this post, because I do not know exactly how to ask it.
I have three tables. One with users, one with foods and one with the users rating of the foods, like such (simplified example):
Foods
id name type
---------------------
1 Apple fruit
2 Banana fruit
3 Steak meat
Users
id username
-----------------
1 Mark
2 Harrison
3 Carrie
Scores (fid = food id, uid = user id)
fid uid score
---------------------
1 1 3
1 2 5
2 1 2
3 2 3
Now, I have this query, which works perfectly:
SELECT fn.name as Food, ROUND(AVG(s.score),1) AS AvgScore FROM Foods fn LEFT JOIN Scores s ON fn.id = s.fid GROUP BY fn.id ORDER BY fn.name ASC
As you can tell, it lists all names from Foods including an average from all users ratings of the food.
I also want to add the unique users own score. (Assume that when Mark is logged in, his uid is set in a session variable or whatever)
I need the following output, if you are logged in as Mark:
Food AvgScore Your Score
Apple 4 3
I have made several attempts to make this happen, but I cannot find the solution. I have learned that if you have a question, it is very likely that someone else has asked it before you do, but I do not quite know how to phrase the question, so I get no answers when googling. A pointer in the right direction would be much appreciated.
You can try with case:
SELECT fn.name as Food,
ROUND(AVG(s.score),1) AS AvgScore,
sum(case s.uid = $uid when s.score else 0 end) as YourScore
FROM Foods fn
LEFT JOIN Scores s ON fn.id = s.fid
GROUP BY fn.id
ORDER BY fn.name ASC
$uid is variable off course.
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 7 years ago.
Improve this question
I have three tables in my database which are listed below:
Table: teams_info
team_id team_name entry_year status
1 team 1 2015 1
2 team 2 2015 1
3 team 2 2016 1
Table: team_players
player_id team_id status members_id position
1 1 0 1 1
2 1 1 2 2
3 1 1 3 3
4 1 1 4 4
5 2 0 5 1
6 2 0 6 2
7 2 1 7 3
Table: members
members_id first_name surname gender
1 joe blogg male
2 james smith male
3 sarah marshall female
4 tony walker male
5 peter jones male
6 jessica varley female
7 jane varley female
I'm trying to get my head around how I would get the following information,
1) How many team_players from team_info.entry_year = 2015 have accepted the to join a team (this will be all players with status = 1)
2) How many team_players from team_info.entry_year = 2015 have been invited (basically counting all records that belong to 2015 teams in table team_info)
3) The total Males players from 2015 teams.
4) The total female players from 2015 teams.
I'm fairly new to SQL and it seems I have made things complicated whilst trying to follow the best standards, however I can't wrap my head around where to start.
Are you using mysql or some other RDBMS?
I'll assume mysql here, as there are a variety of join syntaxes you can use and they vary by database.
What you want to do here is do an INNER join of all 3 tables which will give you one row per intersection.
Fortunately, you have a good basic normalized structure that has separated the TEAM entity from the MEMBERS (players).
Because your app supports "seasons" you have a good many-to-many resolver table in team_players.
So, to join the tables together, strictly speaking it doesn't really matter which table you start with, but in a case like this, I will start with the many to many resolution table:
SELECT *
FROM team_players as tp LEFT JOIN teams_info as ti ON (ti.team_id = tp.team_id) LEFT JOIN members as m ON (m.members_id = tp.members_id) At this point, you are inner joining and should have 1 row essentially for every match, which is going to be one row for every row in team_players.
In your examples, you want a count, so rather than SELECT , you just want COUNT() as 'some_name'. What you alias that name to be is up to you. For example you could have:
SELECT count(*) as accepted_in_2015
FROM team_players as tp
LEFT JOIN teams_info as ti ON (ti.team_id = tp.team_id)
LEFT JOIN members as m ON (m.members_id = tp.members_id)
Of course, what is missing now is the filtration. You can add these with a WHERE clause in most cases, but I typically add them in the appropriate join criteria. So when I'm adding a WHERE/filtration criteria that has to do with a team, I will put it in the ON that involves the teams_info join.
Where it's a 'member' table criteria (status in your first question) I add that there.
So to answer your first question, this should probably work:
1) How many team_players from team_info.entry_year = 2015
have accepted the to join a team (this will be all players with status
= 1)
SELECT count(*) as accepted_in_2015
FROM team_players as tp
LEFT JOIN teams_info as ti ON (ti.team_id = tp.team_id AND ti.entry_year = 2015)
LEFT JOIN members as m ON (m.members_id = tp.members_id AND m.status = 1)
The other questions are all variations on this same blue print and can be determined the same way, however, in the case of male/female I'd probably just group by and get counts for male vs/ female in one query.
I've been struggling on the following.
I have 3 tables: players, players_clothes, and teams_clothes.
Table players:
id user team_id
1 tom 4
2 robo 5
3 bob 4
So tom and bob are both on the same team
Table players_clothes:
id clothes_id p_id
1 13 1
2 35 3
3 45 3
Bob has clothing article 35 and 45, robo has none.
Table teams_clothes:
id clothes_id team_id
1 35 4
2 45 4
3 55 4
4 65 5
This shows which teams have rights to which articles of clothing. The problem: tom is wearing an article of clothing that does no belong to his team... Let's assume this is illegal.
I'm having trouble figuring out how to capture all those who are wearing illegal clothes for a particular team.
SELECT pc.clothes_id FROM players AS p
JOIN players_clothes AS pc
ON p.id = pc.p_id
AND p.team_id = 4 GROUP BY pc.clothes_id
(I group by players_clothes.clothes_id because believe it or not, two players can be assigned the same piece of clothing)
I think this results the following set (13, 35, 45)
Now I would like to check against the actual set of clothes that team 4 owns.
SELECT clothes_id FROM teams_clothes WHERE team_id = 4 and this return (35, 45, 55)
How can I create a query so that it returns (13)? I've tried things like NOT EXISTS IN but I think the GROUP BY players_clothes.clothes_id part gets in the way
I suggest
select * from A where team_id = $team_id join B on B.a_id = A.id
where not exists
(
select 1 from C where C.clothes_id = B.clothes_id and team_id = $team_id
)
Basically, we find all As who are on their team and for each A join to all clothing they wear, and then only return the row IF we can't find indication in table C that the clothing is on our team (this covers not existent in C and exists but in the wrong team on C)
This should do the trick:
SELECT b.a_id, b.clothes_id
FROM
b INNER JOIN a
ON b.a_id = a.id
LEFT OUTER JOIN c
ON a.team_id = c.team_id
WHERE
c.clothes_id = NULL
The thought is to do an outer join on the combination of tables A/B against table C. And then only look for the cases where c.clothes_id is NULL, which would represent those cases where there is no relational match on the outer join (i.e. the clothes item is not approved for that user's team).
Not sure if this is too late for you, but I'd change the database model itself to make this situation impossible in the first place:
("Unimportant" fields omitted for brevity, including surrogate keys such as PLAYER_ID.)
Note how TEAM_ID migrates through the identifying relationship from TEAM to PLAYER, and then to the PLAYER_ARTICLE, where it merges with the same field migrated through the TEAM_ARTICLE. Since there is only one physical TEAM_ID field in the PLAYER_ARTICLE table, you can never insert a row that would reference different teams.
To put it in more abstract terms: this is a diamond-shaped dependency, where TEAM is at the top and PLAYER_ARTICLE at the bottom of the diamond. The merger at the bottom (enabled by the usage of identifying relationships) ensures sides must always point to the same top.
Your example data would be represented like this...
PLAYER:
TEAM_ID PLAYER_NO
4 1 -- Tom
5 1 -- Robo
4 2 -- Bob
TEAM_ATRICLE:
TEAM_ID ARTICLE_ID
4 35
4 45
4 55
5 65
PLAYER_ARTICLE:
TEAM_ID PLAYER_NO ATRICLE_ID
4 1 13 -- Tom: this is impossible (FK violation).
4 2 35 -- Bob
4 2 45 -- Bob
Assume I have 4 tables:
Table 1: Task
ID Task Schedule
1 Cut Grass Mon
2 Sweep Floor Fri
3 Wash Dishes Fri
Table 2: Assigned
ID TaskID (FK) PersonID (FK)
1 1 1
2 1 2
3 2 3
4 3 2
Table 3: Person
ID Name
1 Tom
2 Dick
3 Harry
Table 4: Mobile
ID PersonID (FK) CountryCode MobileNumber
1 1 1 555-555-5555
2 2 44 555-555-1234
3 3 81 555-555-5678
4 3 81 555-555-0000
I'm trying to display the
Task on a certain day
Name of person assigned to task
Phone numbers of said person
I think it should be something like the following, but I'm not sure how to set up the conditions so that the results are limited correctly:
SELECT T.ID, T.Task, P.Name, M.MobileNumber
FROM Task AS T
LEFT JOIN Assigned AS A
ON T.ID = A.TaskID
LEFT JOIN Person AS P
ON A.PersonID = P.ID
LEFT JOIN Mobile AS M
ON M.PersonID = P.ID
WHERE T.Schedule = Fri
My goal is to fetch the following information (it will be displayed differently):
Tasks Name MobileNumber
Sweep Floor, Wash Dishes Dick, Harry 44-555-555-1234, 81-555-555-5678, 81-555-555-0000
Of course, if JOIN is the wrong way to do this, please say so.
It's unclear what you want to do with duplicate data in this case, but you should be looking at using inner joins instead of outer joins, and using something like group_concat() to combine the phone numbers.