I have a table which contains data from a radio station, and which songs it played. All the songs played are stored in a table named 'radio_data'. This table looks like this:
-----------------------------------------------
| id | artist_id | song_id | play_date |
| 1 230 420 2017-5-12 12:00 |
| 2 212 971 2017-5-12 12:01 |
| 3 230 420 2017-5-12 13:00 |
| 4 230 420 2017-5-12 15:00 |
| 5 212 971 2017-5-12 15:02 |
-----------------------------------------------
I have a page where some statistics for one specific song is displayed. On this page i would like to show the rank of the song, based on how much it has been played.
Let's say that if i am om the page for song_id 420, it would rank as place 1 out of 2 songs.
I have no idea where to start. I have this query to group the songs:
SELECT COUNT(`id`) AS `playcount`, `artist_id`, `song_id` FROM `radio_data` GROUP BY `song_id` ORDER BY `playcount` DESC
This gives me the following result:
-----------------------------------
| playcount | artist_id | song_id |
| 3 230 420 |
| 2 212 971 |
-----------------------------------
Thanks in advance for your help!
You can use user variables for displaying the rank:
set #rn := 0;
select #rn := #rn + 1 as rank,
song_id,
artist_id,
count(*) as times_played
from your_table
group by song_id, artist_id
order by times_played desc;
If you want to get top, say 10, songs you can add a limit 10 at the end.
SELECT
song_id, count(id) played_times, #rank := #rank +1 rank
FROM
(
songs_plays CROSS JOIN (SELECT #rank := 0)rank
)
GROUP BY song_id
ORDER BY played_times DESC
the result is
+------------+--------------+--------+
| song_id | played_times | rank |
+------------+--------------+--------+
| 420 | 3 | 1 |
| 971 | 2 | 2 |
+------------+--------------+--------+
run it live on SQL fiddle (http://sqlfiddle.com/#!9/1c48d8/5)
Related
i am trying to get rank and number of same rank by votes but unfortunately no success.
Here my table structure:
| ID| user_id | votes |
| --| ------- | ----- |
| 1 | D10 | 15 |
| 2 | D5 | 9 |
| 3 | D20 | 9 |
| 4 | D23 | 7 |
| 5 | D35 | 3 |
| 6 | D65 | 2 |
I need the rank of user according to votes, referring to above table i need the rank as:
| user_id | Rank|
| ------- | ----|
| D10 | 1 |
| D5 | 2 |
| D20 | 2 |
| D23 | 3 |
| D35 | 4 |
| D65 | 5 |
and also i need the number of rank, referring to above ranks i need:
Rank 1 = 1
Rank 2 = 2
Rank 3 = 1
Rank 4 = 1
rank 5 = 1
i tried to get rank :
SELECT user_id, votes, FIND_IN_SET( votes, (
SELECT GROUP_CONCAT( DISTINCT votes
ORDER BY votes DESC ) FROM table)
) AS rank
FROM votes
the above query i tried referring to this answer to get the ranks but i am getting error:
#1064 - You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use
near '( votes , (SELECT GROUP_CONCAT( DISTINCT votes ORDER BY votes DESC
)
i need the desired result using PHP and MySQL.
On MySQL 8+ you could use windows function dense_rank and count over
with votes_rank as (
select *,
dense_rank() over (order by votes desc) as rnk
from votes
) , count_rank as
( select votes_rank.*,
count(*)over (partition by rnk) as cnt
from votes_rank
) select id,
user_id,
votes,
rnk as votes_rank,
cnt as count_rank
from count_rank;
https://dbfiddle.uk/o1DiPyDz
Consider the following data,
CREATE TABLE votes (
id int,
user_id varchar(10),
votes int );
insert into votes values (1,'D10',15), (2,'D5 ',9), (3,'D20',9), (4,'D23',7), (7,'D50',7), (5,'D35',3), (6,'D65',2);
Result:
id user_id votes votes_rank count_rank
1 D10 15 1 1
2 D5 9 2 2
3 D20 9 2 2
4 D23 7 3 2
7 D50 7 3 2
5 D35 3 4 1
6 D65 2 5 1
Edit,
On MySQL version <8
select tbl.id,tbl.user_id,tbl.votes,tbl.rnk,votes_count
from (SELECT a.id,
a.user_id,
a.votes,
count(b.votes)+1 as rnk
FROM votes a
left join votes b on a.votes<b.votes
group by a.id,a.user_id,a.votes
order by a.votes desc
) as tbl
inner join (select rnk,count(rnk) as votes_count
from ( SELECT a.id,
a.user_id,
a.votes,
count(b.votes)+1 as rnk
FROM votes a
left join votes b on a.votes<b.votes
group by a.id,a.user_id,a.votes
order by a.votes desc
) a2
group by rnk
) as tbl1 on tbl1.rnk = tbl.rnk;
https://dbfiddle.uk/XlsBjrZO
Given an example of table:
id | item_id | user_id | bid_price
----------------------------------
The task is to select rows with minimum bid_price for each item_id in the provided set.
For example: item_id = [1, 2, 3] - so I need to select up to three (3) rows, having a minimum bid_price.
Example of data:
id | item_id | user_id | bid_price
----------------------------------
1 | 1 | 11 | 1
2 | 1 | 12 | 2
3 | 1 | 13 | 3
4 | 1 | 14 | 1
5 | 1 | 15 | 4
6 | 2 | 16 | 2
7 | 2 | 17 | 1
8 | 3 | 18 | 2
9 | 3 | 19 | 3
10 | 3 | 18 | 2
Expected result:
id | item_id | user_id | bid_price
----------------------------------
1 | 1 | 11 | 1
7 | 2 | 17 | 1
8 | 3 | 18 | 2
Actually, I'm using Symfony/Docine DQL, but it will be enough with a plain SQL example.
For the all the columns in the rows you could use a inner join on subselect for min bid price
select m.id, m.item_id, m.user_id, m.bid_price
from my_table m
inner join (
select item_id, min(id) min_id, min(bid_price) min_price
from my_table
where item_id IN (1,2,3)
group by item_id
) t on t.item_id = m.item_id
and t.min_price= m.bid_price
and t.min_id = m.id
or .. if you have some float data type you could use a acst for unsigned
select m.id, m.item_id, m.user_id, cast(m.bid_price as UNSIGNED)
from my_table m
inner join (
select item_id, min(id) min_id, min(bid_price) min_price
from my_table
where item_id IN (1,2,3)
group by item_id
) t on t.item_id = m.item_id
and t.min_price= m.bid_price
and t.min_id = m.id
You can use MIN() with GROUP BY in the query:
SELECT id, item_id, MIN(bid_price) AS min_bid, user_id
FROM your_tbl
GROUP BY item_id
HAVING item_id in(1, 2, 3);
Use this query:
SELECT id, item_id, user_id, min(bid_price) as bid_price
FROM YOUR_TABLE_NAME
GROUP BY item_id;
I'm looking for a way in MySql to select the most occurring value in one column.
E.g. this table
+-------+-------+
| Name | Signin|
+-------+-------+
| Name1 | 1 |
| Name1 | 2 |
| Name1 | 1 |
| Name1 | 3 |
| Name1 | 2 |
| Name1 | 2 |
| Name2 | 4 |
| Name2 | 5 |
| Name2 | 5 |
| Name2 | 5 |
| Name2 | 5 |
| Name2 | 6 |
+-------+-------+
The column Signin has two=1, three=2, one=3 sow for the Name1 the most recent value is 2, for the Name2 the most recent value is 5 as in the column Signin are one=4, four=5, one=6
The result I need is like this
Name1 - 2
Name2 - 5
What you are looking for is called the "mode" in statistics. Most databases support with CTEs or window functions which simplify the calculation. If your data is not too big, I think this following aggregation trick is the easiest method:
select name,
substring_index(group_concat(signin order by cnt desc), ',', 1) as signin
from (select name, signin, count(*) as cnt
from t
group by name, signin
) ns
group by name;
The above does not always work. One possibility is sgeddes's approach using two aggregations. Another is to use variables:
select ns.*
from (select ns.*,
(#rn := if(#n = name, #rn + 1,
if(#n := name, 1, 1)
)
) as rn
from (select name, signin, count(*) as cnt
from t
group by name, signin
order by name, count(*) desc
) ns cross join
(select #n := '', #rn := 0) params
) ns
where seqnum = 1;
I have a table that looks something like below without the rank field. I want to put that rank field as it is in the table below. How can I achieve it in MySQL?
# name aa bb cc total | rank
1 name1 20 20 30 70 | 1
2 name2 10 20 30 60 | 2
3 name3 20 10 25 55 | 3
4 name4 20 20 30 70 | 1
5 name5 10 10 20 40 | 4
Here is a way to do it, the result will be sorted with respect to the total.
mysql> create table test (id int, name varchar(100),total int);
Query OK, 0 rows affected (0.13 sec)
mysql> insert into test values
-> (1,'name1',70),
-> (2,'name2',60),
-> (3,'name3',55),
-> (4,'name4',70),
-> (5,'name5',40);
Query OK, 5 rows affected (0.02 sec)
select
id,
name,
case
when #cur_rank = total then #rank
else #rank := #rank + 1
end as rank,
#cur_rank := total as total
from test ,(select #rank:=0, #cur_rank:=0)r
order by total desc ;
+------+-------+------+-------+
| id | name | rank | total |
+------+-------+------+-------+
| 1 | name1 | 1 | 70 |
| 4 | name4 | 1 | 70 |
| 2 | name2 | 2 | 60 |
| 3 | name3 | 3 | 55 |
| 5 | name5 | 4 | 40 |
+------+-------+------+-------+
Try this:-
SELECT #, name, aa, bb, cc, total, FIND_IN_SET( total, (
SELECT GROUP_CONCAT( total ORDER BY total DESC )
FROM your_tab
)
) AS rank
FROM your_tab;
I have a table of users with points column in it. User id is not autoincrement, but it is user ID from Twitter.
I'm trying to select user by username (so always 1 user) and select 10 rows before it and 10 rows after it.
Also, it should be ordered by points and I should get ranking of selected user.
I'm using Laravel 4 and Eloquent, but I'm pretty sure it can't be done with Eloquent.
+-----------+--------------+------------+
| id | username | vote_count |
+-----------+--------------+------------+
| 123456789 | user1 | 150 |
| 123456789 | user2 | 101 |
| 123456789 | user3 | 90 |
| 123456789 | user4 | 88 |
| 123456789 | user5 | 70 |
| 123456789 | user6 | 67 |
| 123456789 | user7 | 65 |
| 123456789 | user8 | 55 |
| 123456789 | user9 | 54 |
| 123456789 | user10 | 45 |
| 123456789 | user11 | 44 |
| 123456789 | user12 | 42 |
+-----------+--------------+------------+
Let's say I want to order this table by vote_count, than select user5 and select 2 users that are before and after it in given order.
Hope I'm being clear with this one
Something like this :
SQLFiddle demo
select * from
(
select * from
(
select * from t where vote_count<=
(select vote_count
from t
where username ='user5')
ORDER BY vote_count desc
LIMIT 3
) as T1
UNION
select * from
(
select * from t where vote_count>
(select vote_count
from t
where username ='user5')
ORDER BY vote_count ASC
LIMIT 2
) as T2
) as T3 ORDER BY VOTE_COUNT DESC
You could use union
(SELECT id, vote_count
FROM `table`
WHERE id > 123456789
LIMIT 10)
UNION
(SELECT id, vote_count
FROM `table`
WHERE id <= 123456789
LIMIT 10)
ORDER BY vote_count
You can check the SQL FIDDLE
select * from ( (select A.vote_count,A.username from t A join t B on A.vote_count<B.vote_count where B.username='user5' order by A.vote_count DESC limit 2)
UNION
(select A.vote_count,A.username from t A join t B on A.vote_count>=B.vote_count where B.username='user5' order by A.vote_count limit 3)) as T order by vote_count desc