I have a table (action_tbl) as follows:
ActionID | Frame | Player_ID
----------------------------
1234 | 15 | 1
1235 | 15 | 1
1236 | 30 | 1
1237 | 280 | 1
1238 | 10 | 2
1239 | 60 | 2
1240 | 320 | 2
I'd like to write a script in MySQL to count number of actions for each player during a 240 frame period (for frame between 0-240, Frame_Period is 0, 241-480, 1, etc).
So the output should be as follow:
Count_Actions | Frame_Period | Player_ID
----------------------------
3 | 0 | 1
1 | 1 | 1
2 | 0 | 2
1 | 1 | 2
Edited
Sql Fiddle Demo
SELECT frame_id as Frame_Period, `Player_ID`, count(*) as Count_Actions
FROM action_tbl a
JOIN (SELECT 0 as frame_id, 0 low_limit, 240 high_limit
UNION
SELECT 1 as frame_id, 241 low_limit, 480 high_limit
UNION
SELECT 2 as frame_id, 481 low_limit, 720 high_limit
UNION
SELECT 3 as frame_id, 721 low_limit, 960 high_limit
) as frame_range
ON a.`Frame` between frame_range.low_limit
and frame_range.high_limit
GROUP BY `Player_ID`, frame_id
ORDER BY `Player_ID`, frame_id
OUTPUT
| frame_id | Player_ID | Count_Actions |
|----------|-----------|---------------|
| 0 | 1 | 3 |
| 1 | 1 | 1 |
| 0 | 2 | 2 |
| 1 | 2 | 1 |
Second aproach
SELECT truncate((Frame - 1) / 240, 0) as Frame_Period,
`Player_ID`,
count(*) as Count_Actions
FROM action_tbl
GROUP BY `Player_ID`, Frame_Period
ORDER BY `Player_ID`, Frame_Period
Related
I need a help to create a view in MySQL.
I have a table in the name of competitions like below:
+---------+-----+-----+-----+
|id| name |rank1|rank2|rank3|
+--+------+-----+-----+-----+
| 1| cmpt1| 4 | 3 | 9 |
| 2| cmpt2| 3 | 7 | 8 |
| 3| cmpt3| 4 | 1 | 2 |
| 4| cmpt4| 5 | 8 | 4 |
| 5| cmpt5| 9 | 3 | 2 |
| 6| cmpt6| 1 | 8 | 2 |
+--+------+-----+-----+-----+
the rank1,2,3 values refer to the player id who has such rank at the end of that competition.
Now I want to create a MySQL view to show each player's total medals. Rank 1, 2, and 3 received gold, silver, and bronze medal respectively.
The output of the view will be like following table:
+------+------------+-------------+-------------+
|player| gold_medals|silver_medals|bronze_medals|
+------+------------+-------------+-------------+
| 1 | 4 | 7 | 1 |
| 2 | 7 | 0 | 9 |
| 3 | 1 | 4 | 6 |
| 4 | 0 | 2 | 8 |
| 5 | 2 | 8 | 0 |
| 6 | 3 | 1 | 1 |
+------+------------+-------------+-------------+
Thanks in advance
I assumed you have another table for list players :
select p.playerid
, count(case when playerid = rank1 then 1 end) gold_medals
, count(case when playerid = rank2 then 1 end) silver_medals
, count(case when playerid = rank3 then 1 end) bronze_medals
from
players p
left join ranks r
on p.playerid in (rank1, rank2, rank3)
group by p.playerid
playerid | gold_medals | silver_medals | bronze_medals
-------: | ----------: | ------------: | ------------:
1 | 1 | 1 | 0
2 | 0 | 0 | 3
3 | 1 | 2 | 0
4 | 2 | 0 | 1
5 | 1 | 0 | 0
6 | 0 | 0 | 0
7 | 0 | 1 | 0
8 | 0 | 2 | 1
9 | 1 | 0 | 1
db<>fiddle here
You can unpivot and aggregate:
select playerid,
sum(ranking = 1) as num_gold,
sum(ranking = 2) as num_silver,
sum(ranking = 3) as num_bronze
from ((select rank1 as playerid, 1 as ranking
from ranks
) union all
(select rank2, 2 as ranking
from ranks
) union all
(select rank3, 3 as ranking
from ranks
)
) p
group by playerid;
Note: This only includes players who have a ranking. Your question doesn't include a source of all players, so that seems sufficient.
Here is a db<>fiddle.
Note that older versions of MySQL (pre-5.7 I think) don't support subqueries in the FROM clause of views. Happily that restriction is no longer in force.
Let's say, in given num_table, there is a column, in which only numbers from 1 to 35 are stored.
Code for count nums in last 25rows is:
select num, count(*)
from (select C_1 as num from num_table order by id desc limit 25) n
group by num
order by num asc;
Result:
| num | count(*) |
|------|----------|
| 2 | 1 |
| 3 | 1 |
| 4 | 1 |
| 5 | 2 |
| 10 | 1 |
| 11 | 1 |
| 12 | 1 |
| 15 | 1 |
| 16 | 2 |
| 17 | 1 |
| 20 | 1 |
| 21 | 1 |
| 22 | 1 |
| 23 | 1 |
| 25 | 1 |
| 28 | 2 |
| 29 | 2 |
| 30 | 1 |
| 32 | 2 |
|------|----------|
How to get a result, where nums from 1 to 35 - which occured 0 times within last 25 rows - will be also displayed?
Example of desired result:
| num | count(*) |
|------|----------|
| 1 | 0 |
| 2 | 1 |
| 3 | 1 |
| 4 | 1 |
| 5 | 2 |
| 6 | 0 |
| 7 | 0 |
| 8 | 0 |
| 9 | 0 |
| 10 | 1 |
| ... | ... |
| 35 | 0 |
Maybe the quickest way is to make your existing query as sub-query and LEFT JOIN your num_table with it like :
SELECT A.C_1, IFNULL(cnt,0) total_count
FROM num_table A
LEFT JOIN
(SELECT num, COUNT(*) cnt
FROM (SELECT C_1 AS num FROM num_table ORDER BY id DESC LIMIT 25) n
GROUP BY num) B
ON A.C_1=B.num
GROUP BY A.C_1, cnt
ORDER BY A.C_1 ASC;
Here's a fiddle for reference:
https://dbfiddle.uk/?rdbms=mysql_5.7&fiddle=3ced94d698fd8a55a8ad07a9d3b42f3d
And by the way, the current result you're showing is only 24 rows despite you did LIMIT 25 in the first sub-query. So in my example fiddle, the result is slightly different.
Here is another way to solve your problem.
In this solution, first, you need a table with numbers between 1 and 35, but only for the query, so then you can left join (because with a left join you can have also 0 counter values) it with your existent num_table.
You can do it like this:
WITH RECURSIVE numbers(id) AS (
SELECT 1 as id
UNION ALL
SELECT id+1 FROM numbers WHERE id < 35
)
SELECT numbers.id AS num, count(nt.id) AS total
FROM numbers
LEFT JOIN (SELECT C_1 FROM num_table ORDER BY id DESC LIMIT 25) nt ON (nt.C_1 = numbers.id)
GROUP BY numbers.id
I have this table test_table below
USER_ID | YEAR | MONEY
----------------------
1 | 0 | 0
1 | 12 | 12
1 | 48 | 12
2 | 15 | 15
2 | 10 | 20
3 | 0 | 0
So I am trying to return the row which has the highest money. For example, the row return would be like this
USER_ID | YEAR | MONEY
----------------------
1 | 12 | 12
1 | 48 | 12
2 | 10 | 20
3 | 0 | 0
But because User ID 1 has the same value for money, I would like to check for the highest year of that money amount and return the result. The expected result should be
USER_ID | YEAR | MONEY
----------------------
1 | 48 | 12
2 | 10 | 20
3 | 0 | 0
Is it possible to get row like this?
Here is the link to test your query online
http://sqlfiddle.com/#!9/2e5660/1
You can try using correlated subquery
DEMO
select userid, moneyval,max(year) as year
from
(
select * from t a
where moneyval in
(select max(moneyval) from t b where a.userid=b.userid)
)A group by userid, moneyval
OUTPUT:
userid moneyval year
1 12 48
2 20 10
3 0 0
You can use not exists to get the rows with maximum values in money (and year):
select t.*
from test_table t
where not exists (
select 1 from test_table
where userid = t.userid and (
money > t.money or (money = t.money and year > t.year)
)
)
See the demo.
Results:
| userid | money | year |
| ------ | ----- | ---- |
| 1 | 12 | 48 |
| 2 | 20 | 10 |
| 3 | 0 | 0 |
We have one table- Product_table:
product_id | company_id | Status | must_show
1 | 23 | 1 | 1
2 | 23 | 1 | 1
3 | 23 | 1 | 0
4 | 23 | 1 | 0
5 | 23 | 0 | 0
6 | 24 | 1 | 0
7 | 24 | 1 | 0
8 | 24 | 1 | 0
9 | 24 | 1 | 0
10 | 24 | 0 | 0
We need to find the max product_id of company where status is 1. For that we are using below query:
select * from Product_table as pt
JOIN (select MAX(product_id) as extid from Product_table) t1 ON t1.extid =
pt.product_id where company_id in (23,24) and status = 1 group by company_id;
Result:
product_id| company_id| Status | must_show
4 | 23 | 1 | 0
9 | 24 | 0 | 0
This query is fine but we have an issue here.
If value for must_show is 1 then we need show max_product id for company with must_show=1 and status=1.
If value for must_show is 0 then we need show max_product id for company with status=1.
Expected Result:
product_id| company_id| Status | must_show
2 | 23 | 1 | 1
9 | 24 | 1 | 0
Please give me the path to find a solution. Thanks!
Please try below query:
select max(t.product_id) product_id, t.company_id, t.status, t.must_show from
( select p1.product_id, p1.company_id, p1.status, p1.must_show
from product_table p1
where status = 1
and must_show = (
select max(must_show) from product_table p2 where p2.company_id = p1.company_id)
) as t group by t.company_id;
Output:
+------------+------------+--------+-----------+
| product_id | company_id | status | must_show |
+------------+------------+--------+-----------+
| 2 | 23 | 1 | 1 |
| 9 | 24 | 1 | 0 |
+------------+------------+--------+-----------+
company_id in (23,24)- I think you don't need this condition as there are only these two company_id present in your table as per your question data.
I want to count the number of messsages per user, per day for the following table:
+---------+---------+------------+
| msg_id | user_id | m_date |
+-------------------+------------+
| 1 | 1 | 2011-01-21 |
| 2 | 1 | 2011-01-23 |
| 3 | 1 | 2011-01-23 |
| 5 | 2 | 2011-01-23 |
| 6 | 2 | 2011-01-24 |
| 8 | 1 | 2011-01-23 |
| 9 | 2 | 2011-01-23 |
| 10 | 1 | 2011-01-24 |
+---------+---------+------------+
The desired outpur would be:
1 2011-01-21 1
2 2011-01-21 0
1 2011-01-22 0
2 2011-01-22 0
1 2011-01-23 3
2 2011-01-23 2
1 2011-01-24 1
2 2011-01-24 1
I use the following query:
SELECT m_date, COUNT(msg_id ) AS volume
FROM messages
GROUP BY user_id, m_date
ORDER BY user_id, m_date ASC
But here, days with a volume of zero are being left out of the resultset:
1 2011-01-21 1
1 2011-01-23 3
2 2011-01-23 2
1 2011-01-24 1
2 2011-01-24 1
I want those days in the resultset, however. So I understood I should make use of a "daterange" table, which contains all the dates for which I want a result:
+---------+------------+
| date_id | d_date |
+---------+------------+
| 1 | 2011-01-21 |
| 2 | 2011-01-22 |
| 3 | 2011-01-23 |
| 4 | 2011-01-24 |
+---------+------------+
However, I don't know how to use this table in accordance with the first one to get the resultset I need. Do you?
This could be accomplished using cross join:
SELECT user_id, d_date,
COUNT(CASE WHEN messages.m_date = d.d_date then 1 end) Volume
FROM messages
CROSS JOIN datetable d
GROUP BY messages.user_id, d.d_date
ORDER BY messages.user_id, d.d_date ASC
Sql Fiddle demo.