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;
Related
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.
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.
I have one SQL query with result table having a list of 700 userids and the corresponding gameids (games played by the user; there are totally 1000 games).
One user might have played more than one games and one gameid may be associated with more than one userid. I have another table in the database that has the list of all gameids and their respective attributes.
I want my final result table to be like: column 1 with all 700 userids (each repeated as many times as the number of gameids associated with the user) and column 2 with the corresponding gameids AND other gameids from the gameid table. These other gameids against each userid should be different from the ones already placed against the userid.
table1
Userid Gameid
1 3
1 4
2 63
2 76
6 99
6 63
table2
Gameid gamename
1 GTA
2 DOTA
1000 xyz
result table
Userid Gameid Gamename
1 3 AOE
1 4 Roadrash
1 1 GTA
1 2 DOTA
1 5 qbc
so on up to
1 1000 xyz
similarly for all userids from table1.
Result table has each user id repeated 1000 times and the top n gameids against each userid are the ones from table1(games the particular users have played) and the rest of the gameids are from the 1000 from table 2(therefore each user is mapped against all the gameids with the top ones being the games they've played).
The idea of the data set up is to include a column in the end of the result table that has binary values (1 -> user has played the game, 0 -> user has not played the game). This table is to be used for machine learning.
Build the result table as a union of the games played by users and the games not played by users like so:
select UserId, GameId, GameName, Played
from (
-- games played
select usr.UserId, gme.GameId, gme.GameName, 1 as Played
from USERS usr
inner join GAMES gme on usr.GameId = gme.GameId
union
-- games not played
select usr.UserId, gme.GameId, gme.GameName, 0 as played
from USERS usr, GAMES gme
where gme.GameId not in (
select usr2.GameId
from USERS usr2
where usr2.UserId = usr.UserId
)
)
order by Userid, Played desc, Gameid
The outer select is used to order the results set such that games played are provided first.
I'm trying to LEFT JOIN two tables and GROUP BY a field of the first table in MySQL.
If there are multiple rows in the second table for each record in the first one, a GROUP BY eliminates all records but one of the right table. Is there a way to determine which one it is?
To give you a specific example, I want to get a list of users, joined with the IDs of their (for example) most expensive purchases (or most recent purchases, or whatever..) It seems like an easy task, but I'm frustrated and have asolutely no idea how to do it!
Table 1: Users
userId, userName
1 Frank
2 Sarah
3 Tim
Table 2: Purchases
orderId, userId, value
1 3 14.99
2 2 9.99
3 3 79.99
4 1 2.99
5 2 14.99
SELECT * FROM Users LEFT JOIN Purchases ON Users.userId = Purchases.userId
will return:
userId, userName, orderId, value
1 Frank 4 2.99
2 Sarah 2 9.99
2 Sarah 5 14.99
3 Tim 1 14.99
3 Tim 3 79.99
Now if I GROUP BY userId the result will be:
userId, userName, orderId, value
1 Frank 4 2.99
2 Sarah 2 9.99
3 Tim 1 14.99
Is there a way to decide in this case which orderId is kept or is there a completely other and better way to do this?
I have tried some things like MAX() but this will always only return the highest value of the whole table, not individually for each user.
Thank you in advance, you awesome stackoverflow-community!
best Florian
In strict SQL this Query would not be valid as in a Group by context u should select only fields contained in the group by clause or aggregates.
Mysql however allows this syntax and handles it as "i dont care about this fields", you can not define which of the rows values is selected then.
But you can do it with a query like this:
SELECT u.*,p.* FROM Users u LEFT JOIN
( SELECT userId, max(value) as max_value FROM Purchases GROUP BY userId) p ON u.userId = p.userId
If you want to get the max() pusrchase per user preserving the order like orderid etc you may need to do this
select
u.userId,
u.userName,
p.orderId,
p.value
from Users u
inner join Purchases p on
p.userId = u.userId
inner join
(
select orderId,
max(value) as value,
userId
from Purchases
group by userId
)o
on o.userId = p.userId
AND o.value = p.value
group by u.userId
http://sqlfiddle.com/#!2/1afda/9
I have a database that has a table that has different LIKES that people have. Each like is stored as a different record. The only info I have in each record is userID, likeID.
The search will be based on the current userID that is signed in. So I'm not matching EVERYONE with EVERYONE but instead matching EVERYONE vs 1
So userID 45 might have likeID 3, likeID 6 and likeID 22 in the table (for instance)
What I want to do is have the table return, in descending order userIDs that they match with based on the total likes they match with someone else.
For example, (based on user 45 example above) it would look at userID 1 and see how many of likeID 3, likeID 6 and likeID 22 they have. then it'd go to userID 2 and see how many of likeID 3, likeID 6 and likeID 22 they have.....it'd do this for everyone.
Then it'd show the results for any that have more than 0 matches for those 3 likeIDs:
Matches:
You and UserID 12 share 3 of the same likes.
You and UserID 87 share 3 of the same likes.
You and UserID 22 share 2 of the same likes.
You and UserID 73 share 2 of the smae likes.
You and UserID 71 share 1 of the same likes.
etc...
I hope that explains what I'm trying to do. I don't think the mySQL query will be too hard but right now I'm baffled at how to do it!
THANKS IN ADVANCE!
select
UL2.userID,
count(*) as LikeMatches
from
UserLikes UL1
JOIN UserLikes UL2
on UL1.LikeID = UL2.LikeID
AND UL1.UserID != SingleUserBasisParameter
where
UL1.UserID = SingleUserBasisParameter
group by
UL2.UserID
order by
2 desc
The "2" in the order by is the ordinal column representing the COUNT(*)
select userid,count(*) as common_likes
from table
where likeid in (select likeid from table where userid = 45) and userid <> 45
group by userid
order by common_likes desc
how about:
SELECT COUNT(likes.likeID) as like_count FROM
LIKES as likes,
(SELECT UserID,likeID FROM likes WHERE UserID = $user_id) as user_likes
WHERE
user_likes.likeID = likes.likeID AND user_likes.userID != likes.userID
GROUP BY likes.UserID
ORDER BY like_count
I haven't tested it, but I think that it should at least give you the right idea. The 2nd SELECT finds all the likes of the main user, which you can then use to filter out the other likes.