I have the following SQL relationship
user has many games
games has may users
User
----
id | name | age |
__________________
1 | mike | 11 |
2 | jeff | 12 |
3 | jake | 31 |
4 | lemd | 81 |
Game
-----
id | name | time |
_____________________
1 | froyo | 11:10 |
2 | honey | 12:22 |
3 | combb | 13:00 |
4 | lolli | 14:00 |
User_Game
----------
| userid | game_id |
___________________
| 1 | 2 |
| 2 | 2 |
| 3 | 1 |
| 4 | 3 |
| 1 | 2 |
| 2 | 4 |
| 2 | 1 |
For each of the users is there a way to get a
list of games that they have played including the number
of games that each user participated in.
Edit
I tried this query
Select User.name, User.age
from User
inner join User_Game
on User.id=User_Game.userid;
However not sure how I could add the count to it
SELECT
userid,
GROUP_CONCAT(game_id) as game_list,
COUNT(*) as total_games
FROM
USER_GAME
GROUP BY
userid;
Related
I need to find the sum of credits from click_stats where source = 'reward' for all users who have claimed at least one of the 3 promo codes AND have the total clicks displayed.
Tables:
+---------------------------------------------+
| click_stats |
+----+---------+--------+--------+------------+
| ID | Credits | Userid | Source | Clicked |
+----+---------+--------+--------+------------+
| 1 | 10 | jon | reward | 1602216005 |
| 2 | 5 | bob | reward | 1602216504 |
| 3 | 5 | jon | reward | 1602216137 |
| 4 | 5 | bob | reward | 1602216138 |
| 5 | 10 | jon | reward | 1602216139 |
| 6 | 5 | jon | reward | 1602216140 |
| 7 | 10 | bob | reward | 1602216150 |
| 8 | 10 | jon | reward | 1602216150 |
| 9 | 10 | sue | reward | 1602216150 |
| 10 | 10 | sue | prize | 1602216150 |
+----+---------+--------+--------+------------+
+-----------------------+
| promo_used |
+----+--------+---------+
| id | userid | promoid |
+----+--------+---------+
| 1 | bob | 1 |
+----+--------+---------+
| 2 | bob | 2 |
+----+--------+---------+
| 3 | bob | 3 |
+----+--------+---------+
| 4 | jon | 1 |
+----+--------+---------+
| 5 | jon | 2 |
+----+--------+---------+
+------------------------+
| promo_codes |
+----+----------+--------+
| id | code | reward |
+----+----------+--------+
| 1 | forever1 | 20 |
+----+----------+--------+
| 2 | novgfy1 | 250 |
+----+----------+--------+
| 3 | novgfy2 | 500 |
+----+----------+--------+
My Query:
SELECT
click_stats.userid as Name,
sum(credits) as TotalClicks
FROM click_stats
JOIN promo_used
ON click_stats.userid = promo_used.userid
JOIN promo_codes
ON promo_used.promoid = promo_codes.id
WHERE
click_stats.source = 'reward'
and FROM_UNIXTIME(clicked) > '2020-10-08'
and (promo_codes.name like '%forever%'
or promo_codes.name like 'novgfy%')
group by
Name
having
TotalClicks > 10
Results when I run my query (returning the total number of clicks * number of promo codes used):
+--------------------+
| Results |
+------+-------------+
| Name | TotalClicks |
+------+-------------+
| bob | 60 |
+------+-------------+
| jon | 80 |
+------+-------------+
Results I am wanting (the total number of clicks only):
+--------------------+
| Expected Results |
+------+-------------+
| Name | TotalClicks |
+------+-------------+
| bob | 20 |
+------+-------------+
| jon | 40 |
+------+-------------+
The problem (I suspect) is that it is summing the click_stats every time it finds a match for promo_codes.name. I just need to know if one of them has been used and then return the total clicks for that user.
Your understanding of the problem is correct. The join multiplies the rows whenever a user has more than one of the promo codes, and you end up with the same credit summed several times.
I would recommend exists instead:
select cs.userid as name, sum(cs.credits) as totalclicks
from click_stats cs
where cs.source = 'reward' and exists (
select 1
from promo_used pu
inner join promo_codes pc on pc.id = pu.promoid
where
pu.userid = cs.userid
and (pc.name like '%forever%' or pc.name like 'novgfy%')
)
group by cs.userid
having sum(cs.credits) > 10
I have 4 tables: the first is the client table, which has customer info, and client_id as an auto-increment primary key.
The second and third are identical in structure: they are used to track attendance to 2 different therapy programs. They each have a primary key, and a client_id column to track the client. One of the fields contains units, which I want to sum.
The last table contains the therapists' info.
Basically I want to extract total amount of units for each client from the two attendance tables.
I have tried LEFT JOINS to no avail. I also tried a UNION ALL, but couldn't get it to sum the units.
This is how the tables look:
client:
+---------------------------------------+
| client_id | f_name | l_name | th_id |
|-----------|----------|--------|-------|
| 1 | sherlock | holmes | 1 |
| 2 | john | watson | 4 |
| 3 | hercule | poirot | 3 |
| 4 | jane | marple | 2 |
+---------------------------------------+
therapist:
+--------------------------+
| th_id | f_name | l_name |
|-------|---------|--------|
| 1 | james | kirk |
| 2 | mr | spock |
| 3 | bones | mccoy |
| 4 | nyota | uhura |
+--------------------------+
attendance it:
+-------------------------------+
| it_id | client_id | units |
|-----------|-----------|-------|
| 1 | 1 | 4 |
| 2 | 1 | 4 |
| 3 | 1 | 0 |
| 4 | 1 | 2 |
| 5 | 4 | 0 |
| 6 | 4 | 4 |
| 7 | 4 | 0 |
| 8 | 4 | 2 |
+-------------------------------+
attendance psr:
+-------------------------------+
| it_id | client_id | units |
|-----------|-----------|-------|
| 1 | 1 | 16 |
| 2 | 1 | 16 |
| 3 | 1 | 0 |
| 4 | 1 | 12 |
| 5 | 4 | 0 |
| 6 | 4 | 14 |
| 7 | 4 | 8 |
| 8 | 4 | 10 |
+-------------------------------+
The result should look like this:
+------------------------------------------------------------+
| client_id | total_units_it | total_units_psr | therapist |
|-----------|----------------|-----------------|-------------|
| 1 | 10 | 44 | james kirk |
| 4 | 6 | 32 | mr spock |
+------------------------------------------------------------+
Please excuse the primitive representations, and please don't ask why the tables are designed like that... ;-) Also, I obviously ignored many other fields which are not relevant to the question, such as dates, etc.
Any advice would be appreciated.
Thanks!
You can't use join or you will create Cartesian product and duplicate the rows.
Instead you do a subquery:
SELECT c.*
, (SELECT SUM(units) FROM attendance_it a WHERE a.client_id = c.client_id ) as total_units_it
, (SELECT SUM(units) FROM attendance psr a WHERE a.client_id = c.client_id ) as total_units_psr
, t.*
FROM client c
JOIN therapist t
ON c.th_id = t.th_id
use group by client_id to get the sum of each client. and no need to use join as you have already the ids in column.
I have a query that returns a table that looks something like this:
+------+----------+-------+------+----+
| pID | name | month | q | s |
+------+----------+-------+------+----+
| 1468 | bob | 2 | 1 | 14 |
| 1469 | bob | 2 | 1 | 2 |
| 1470 | bob | 2 | 1 | 9 |
| 1468 | bob | 3 | 1 | 7 |
| 1469 | bob | 3 | 1 | 8 |
| 1470 | bob | 3 | 1 | 11 |
+------+----------+-------+------+----+
and I would like the output to be
+----------+-------+------+-----+
| name | month | q | sub |
+----------+-------+------+-----+
| bob | 2 | 1 | 25 |
| bob | 3 | 1 | 26 |
+----------+-------+------+-----+
Essentially, I want the first two columns of my output to be name, month and q grouped by name and month (they will always have the same data per line in this grouping) and I want the last column to be the SUM of s grouped by name only.
Thanks.
It should be something like this:
SELECT name, month, q, SUM(sub)
FROM table
GROUP BY name, month, q
So I have the following 4 tables (unnecessary columns removed):
match_player:
+----------+-----------+-----------+-------+------+
| match_id | metric_id | player_id | team | elo |
+----------+-----------+-----------+-------+------+
| 1 | 100 | 1 | Alpha | 1140 |
| 2 | 101 | 3 | Beta | 1140 |
| 3 | 102 | 2 | Beta | 1200 |
| 3 | 103 | 3 | Alpha | 1132 |
+----------+-----------+-----------+-------+------+
match:
+----------+---------------------+---------------------+------+--------+-------------+------------+
| match_id | start | end | mode | ranked | goals_alpha | goals_beta |
+----------+---------------------+---------------------+------+--------+-------------+------------+
| 1 | 2016-03-21 04:07:41 | 2016-03-21 04:25:26 | 5v5 | 1 | 4 | 6 |
| 2 | 2016-03-21 03:48:03 | 2016-03-21 04:06:41 | 5v5 | 0 | 5 | 10 |
| 3 | 2016-03-21 03:06:37 | 2016-03-21 03:31:06 | 5v5 | 1 | 7 | 13 |
+----------+---------------------+---------------------+------+--------+-------------+------------+
player:
+-----------+----------+
| player_id | name |
+-----------+----------+
| 1 | Player 1 |
| 2 | Player 2 |
| 3 | Player 3 |
+-----------+----------+
metric:
+-----------+--------+-------+
| metric_id | passes | goals |
+-----------+--------+-------+
| 100 | 10 | 1 |
| 101 | 12 | 0 |
| 102 | 4 | 5 |
| 103 | 9 | 3 |
+-----------+--------+-------+
Now, as the title suggests, I would like to retrieve the last x matches for each player who's player_id is in a list retrieved by a previous query. I know how to get 1 player's last x matches, but for the life of me, I can't figure out how to get the matches for more than 1 player (of course I could use UNION to combine the results of each query for each single player, but I doubt that's efficient when dealing with 100+ players).
It would be great if a "simple" solution were found. If not, I guess I'll have to create another table last_30_matches or so and have that be updated when a match is added to the match table.
Thanks in advance to everybody who takes their time to look into this.
EDIT:
Query to select last x matches for 1 player:
SELECT
*
FROM
`match`
JOIN
match_player ON match_player.match_id = `match`.`match_id`
JOIN
metric ON metric.metric_id = match_player.metric_id
JOIN
player ON player.player_id = match_player.player_id
WHERE
player.player_id = <id>
ORDER BY
`match`.end DESC
LIMIT x
Overview
I have a bunch of data on a competition I'm holding and I want to present it in a better format.
There's 4 tables; the first two are self-explanatory, the points and extras table are essentially the exact same thing, they're just stored in different tables with slightly different column names.
Data
users
+----+---------------+------+
| id | name | team |
+----+---------------+------+
| 1 | John Doe | 1 |
| 2 | Jane Lane | 1 |
| 3 | Jack Black | 4 |
| 4 | Dan Bam | 3 |
| 5 | Pam Jan | 2 |
| 6 | Pop Tart | 2 |
| 7 | John Q | 1 |
| 8 | Hugo Strange | 3 |
| 9 | Jimmy Neutron | 2 |
+----+---------------+------+
teams
+----+-----------------+
| id | name |
+----+-----------------+
| 1 | Team Fun |
| 2 | The Dream Team |
| 3 | In It To Win It |
| 4 | Buddies |
+----+-----------------+
points
+---------+--------+------------+
| user_id | points | event |
+---------+--------+------------+
| 1 | 2 | Basketball |
| 2 | 4 | Basketball |
| 5 | 1 | Basketball |
| 8 | 3 | Basketball |
| 9 | 5 | Basketball |
| 2 | 8 | Volleyball |
| 5 | 5.5 | Volleyball |
| 6 | 6.5 | Volleyball |
| 7 | 2 | Volleyball |
| 8 | 4 | Volleyball |
| 9 | 9.5 | Volleyball |
| 1 | 2.5 | Dodgeball |
| 3 | 3 | Dodgeball |
| 4 | 4 | Dodgeball |
| 6 | 9 | Dodgeball |
| 7 | 2.5 | Dodgeball |
| 9 | 3 | Dodgeball |
+---------+--------+------------+
extras
+---------+--------+---------------------+
| user_id | points | description |
+---------+--------+---------------------+
| 1 | 5 | Great Sportsmanship |
| 3 | 10 | Team Player |
| 8 | 5.5 | Most Improved |
+---------+--------+---------------------+
What I'm Trying To Do
I want to write a query to return all the events (and "extras") a specific team participated in, the total points from all members of the team, and the participating members in that event.
Example below uses Team Fun (Team 1):
+---------------------+--------+--------------------+------------+
| event | points | members | members_id |
+---------------------+--------+--------------------+------------+
| Basketball | 6 | John Doe,Jane Lane | 1,2 |
| Volleyball | 10 | Jane Lane,John Q | 2,7 |
| Dodgeball | 5 | John Doe,John Q | 1,7 |
| Great Sportsmanship | 5 | John Doe | 1 |
+---------------------+--------+--------------------+------------+
If anyone could help me with figuring this out, I'd appreciate it!
SQLFiddle
This is a SQLFiddle with the data schema above - http://sqlfiddle.com/#!2/e8f97a
You can use a UNION to get the extras and points together:
SELECT user_id, points, event
FROM points
UNION ALL
SELECT user_id, points, description AS event
FROM extras
Then using this, you can compile your info with a SUM and a couple of GROUP_CONCATs:
SELECT P.event, SUM(P.points) AS points,
GROUP_CONCAT(U.name) AS members, GROUP_CONCAT(U.id) AS members_id
FROM teams T
INNER JOIN users U ON T.id = U.team
INNER JOIN
(
SELECT user_id, points, event
FROM points
UNION ALL
SELECT user_id, points, description AS event
FROM extras
) P ON U.id = P.user_id
WHERE T.id = #teamId
GROUP BY P.event
SQL Fiddle Example