Sum Team Competition Values with SQL - mysql

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

Related

Getting the most frequent value in a column for a specific person

So I have a table where I collect each person's data.
+--------+-------+--------+---------+----------------+
| player | kills | deaths | assists | champSelection |
+--------+-------+--------+---------+----------------+
| Bob | 1 | 3 | 4 | Horse |
+--------+-------+--------+---------+----------------+
| Bob | 2 | 7 | 5 | Horse |
+--------+-------+--------+---------+----------------+
| Jake | 5 | 5 | 5 | Dog |
+--------+-------+--------+---------+----------------+
| Marie | 2 | 3 | 4 | Dog |
+--------+-------+--------+---------+----------------+
| Marie | 1 | 1 | 9 | Horse |
+--------+-------+--------+---------+----------------+
| Marie | 6 | 7 | 2 | Dog |
+--------+-------+--------+---------+----------------+
And I'm running
SELECT player, sum(kills), sum(deaths), sum(assists)
FROM playerTable
GROUP BY player
ORDER BY player ASC;
How would I add onto my query where what their most frequent champSelection is? I'm trying to display my table as
+--------+-------+--------+---------+----------------+
| player | kills | deaths | assists | champSelection |
+--------+-------+--------+---------+----------------+
| Bob | 3 | 10 | 9 | Horse |
+--------+-------+--------+---------+----------------+
| Jake | 5 | 5 | 5 | Dog |
+--------+-------+--------+---------+----------------+
| Marie | 9 | 11 | 15 | Dog |
+--------+-------+--------+---------+----------------+
Try this:
SELECT player, SUM(kills), SUM(deaths), SUM(assists), frequency
FROM
(
SELECT player, SUM(kills) AS kills, SUM(deaths) AS deaths, SUM(assists) AS assists, champSelection, COUNT(*) AS frequency
FROM playerTable
GROUP BY player, champSelection
ORDER BY frequency DESC
) AS inner_table
GROUP BY player

Fetch last x records for every id in list

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

mysql query order by category top sales

Having trouble with how to do this query. There are three categories, ship,car, plane. I want to order category by most sales.
Here is the SQL fiddle http://sqlfiddle.com/#!2/e3344/1
Here is the table values
id | name | sales | category |
1 | mike | 2 | ship |
2 | john | 11 | car |
3 | david | 13 | ship |
4 | pablo | 24 | car |
5 | greg | 13 | car |
6 | nick | 1 | ship |
7 | anderson | 19 | ship |
8 | matt | 10 | plane |
9 | robbie | 3 | ship |
10 | victor | 1 | ship |
11 | ben | 11 | plane |
12 | rick | 6 | ship |
13 | christopher | 16 | car |
14 | steve | 8 | ship |
15 | claudio | 9 | plane |
How do i add up total sales by category and order DESC?
Try the group by and order by statement.
SELECT category, sum(sales)
FROM table
GROUP BY category
ORDER BY sum(sales) DESC
Edit
Just as a suggestion. Your "category" should be an extra entity in your database model.

Querying a many to many relationship in SQL

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;

Recursive query for MySql - get all subtree

Lets assume that there is a factory that produces products. the factory have catalog of a products, therefore tbl_catalog will be.
+----------------+--------------+-----------------------------------------------+
| catalog_number | catalog_name | details |
+----------------+--------------+-----------------------------------------------+
| 1 | LaptopX | Full assembled laptop - X |
| 2 | Top Half | Where the screen & webcam are |
| 3 | Bottom Half | Where mothereboard, and rest of the parts are |
| 4 | WebCam | WebCam for laptopX |
| 5 | LcdX | Lcd screen for laptopX |
| 6 | Keyboard | set of keys |
| 7 | SSD | Place to store data |
| 8 | Touchpad | If there is no mouse connected |
| 9 | DVD | to play music and watch movies |
| 10 | Lazer Beam | a must have for our DVD |
| 11 | EngineX | EngineX will spin our DVD with no problem |
+----------------+--------------+-----------------------------------------------+
Products composed of other products in the catalog - represented as tree, for our sample, tbl_catalog_tree will be:
+-----------+----------+
| parent_id | child_id |
+-----------+----------+
| 1 | 2 |
| 1 | 3 |
| 2 | 4 |
| 2 | 5 |
| 3 | 6 |
| 3 | 7 |
| 3 | 8 |
| 3 | 9 |
| 9 | 10 |
| 9 | 11 |
+-----------+----------+
That's for the catalog. now lets assemble some products. we need another table - assembly:
+------+----------------+--------------+-------+
| id | catalog_number | assembled_by | qc_by |
+------+----------------+--------------+-------+
| 100 | 11 | Joe | Dan |
| 101 | 11 | Joe | Dan |
| 102 | 11 | Joe | Dan |
| 200 | 10 | Joe | Dan |
| 201 | 10 | Joe | Dan |
| 201 | 10 | Joe | Dan |
| 300 | 9 | Mike | Dan |
| 301 | 9 | Mike | Dan |
| 302 | 9 | Mike | Dan |
+------+----------------+--------------+-------+
but we still don't know what is the connection between the DVD's sub parts so we need tbl_assembly_tree:
+-----------+----------------------+----------+
| parent_id | child_catalog_number | child_id |
+-----------+----------------------+----------+
| 302 | 11 | 100 |
| 302 | 10 | 200 |
| 301 | 11 | 101 |
| 301 | 10 | 201 |
| 300 | 11 | 102 |
| 300 | 10 | 202 |
+-----------+----------------------+----------+
since sub trees can be part of different catalogs (like this DVD that can mee part of laptopX and a future laptopY) we need to know what is the child catalog number for the specific assembly (and not count on the catalog tree structur).
My question is:
How to query so I get a product and all it's sub tree products?
If I want to query the DB about all the assmbled Items of a catalog number and for each assembly to know who build and who qc all it's sub parts recursively,in the above example, If Ill query for DVD I want the answer to be something like:
+----+---------+----------+---------+--------+------------+----------+--------+-------+
| id | cat_num | cat_name | assy_by | sub_id |sub_cat_num | sub_name | ass_by | qc_by |
+----+---------+----------+---------+--------+------------+----------+--------+-------+
| 300| 9 | DVD | Mike | 102 | 11 | EngineX | Joe | Dan |
| 300| 9 | DVD | Mike | 202 | 10 | Lazer B | Joe | Dan |
| 301| 9 | DVD | Mike | 101 | 11 | EngineX | Joe | Dan |
| 301| 9 | DVD | Mike | 201 | 10 | Lazer B | Joe | Dan |
| 302| 9 | DVD | Mike | 100 | 11 | EngineX | Joe | Dan |
| 302| 9 | DVD | Mike | 200 | 10 | Lazer B | Joe | Dan |
+----+---------+----------+---------+--------+------------+----------+--------+-------+
Of course, if all the catalog was one level only I wouldn't put this question here, but I need this to be recursive, so I can see all the subtrees of assemblies for a catalog number I select.
I've build an sqlfiddle for the above example and hope that someone can help me on this
The trick which came in mind is to join the same table several times.
This will give you the result you stated in your question:
SELECT
d.parent_id as id,
a.catalog_number,
a.catalog_name,
e.assembled_by,
d.child_id as sub_id,
b.child_id as sub_cat_num,
c.catalog_name as sub_name,
f.assembled_by as sub_assemly_by,
e.qc_by
FROM
catalog as a, catalog_tree as b,
catalog as c, assembly_tree as d,
assembly as e , assembly as f
WHERE
a.catalog_name = 'DVD'
and a.catalog_number = b.parent_id
and b.child_id = c.catalog_number
and b.child_id = d.child_catalog_number
and d.parent_id = e.id
and d.child_id = f.id
ORDER BY 1