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;
Related
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)
Well I have a table(MYSQL) 'product', with one of the columns named 'category_id' that stores category id from another table 'category' . So there are multiple categories in 'category_id' column. eg table below. Now I want to select fixed number of product from each category(say 2), for eg i want to select 2 latest products from each category from the product table. What mysql query should i use, any idea?
Product:
+-------------+------+---------------------+
| category_id | name | timestamp |
+-------------+------+---------------------+
| 1 | abc | 2016-02-27 16:04:00 |
| 1 | def | 2016-02-28 16:10:00 |
| 1 | ghi | 2016-02-29 16:11:00 |
| 2 | pqr | 2016-02-27 16:04:00 |
| 2 | stu | 2016-02-27 16:05:00 |
| 3 | vwx | 2016-02-28 16:04:00 |
+-------------+------+---------------------+
Expected Result:
Product:
+-------------+------+---------------------+
| category_id | name | timestamp |
+-------------+------+---------------------+
| 1 | def | 2016-02-28 16:10:00 |
| 1 | ghi | 2016-02-29 16:11:00 |
| 2 | pqr | 2016-02-27 16:04:00 |
| 2 | stu | 2016-02-27 16:05:00 |
| 3 | vwx | 2016-02-28 16:04:00 |
+-------------+------+---------------------+
It may help you...
Check the Output in SQL Fiddle Link: http://sqlfiddle.com/#!9/3942d2/6
SELECT
category_id,
name,
tsDate
FROM
(
SELECT
category_id,
name,
tsDate,
#rn := IF(#prev = category_id, #rn + 1, 1) AS rn,
#prev := category_id
FROM Product
JOIN (SELECT #prev := NULL, #rn := 0) AS vars
ORDER BY category_id, tsDate DESC, name
) AS T1
WHERE rn <= 2
Try this :
SELECT x.*
FROM my_table x
JOIN my_table y
ON y.category_id = x.category_id
AND y.timestamp >= x.timestamp
GROUP
BY x.category_id,x.timestamp
HAVING COUNT(*) <= 2;
In reference with my previous question - how to get a sorted result in mysql query?
I am trying to get a sorted result of a table from a MySQL query.
The Table without sorting is as follows :
+---------+---------------+
| id | cat_type |
+---------+---------------+
| 1 | free |
| 2 | free |
| 3 | free |
| 4 | paid |
| 5 | paid |
| 6 | free |
| 7 | free |
| 8 | free |
| 9 | paid |
| 10 | free |
| 11 | free |
| 12 | free |
| 13 | paid |
| 14 | free |
+---------+---------------+
The Sorted Table must be as follows :
+---------+---------------+
| id | cat_type |
+---------+---------------+
| 1 | free |
| 2 | free |
| 4 | paid |
| 3 | free |
| 6 | free |
| 5 | paid |
| 7 | free |
| 8 | free |
| 9 | paid |
| 10 | free |
| 11 | free |
| 13 | paid |
| 12 | free |
| 14 | free |
+---------+---------------+
TASK : All the records are seperated by 3 for clarity and it should be sorted by column cat_type and not by id. The cat_type must be ordered by free, free and paid(Refer 2nd table column records.)
NOTE : The table is dynamic and has 'n' number of records.
How can i accomplish this with a mysql query ?
You can enumerate the rows for free and paid. Probably the easiest way to enumerate two categories is with union all. Then you can do arithmetic to get the "free" records first, and then the "paid" records. I think this will do it:
select id, cat_type
from ((select t.*, #rn1 := #rn1 + 1 as seqnum
from table t cross join (select #rn1 := 0) vars
where cat_type = 'free'
order by id
) union all
(select t.*, #rn2 := #rn2 + 1 as seqnum
from table t cross join (select #rn2 := 0) vars
where cat_type = 'paid'
order by id
)
) t
order by (case when cat_type = 'free' then seqnum*1.0 else 2 * seqnum + 0.5 end)
I got an answer for my question and it works well for me.
The following code did the trick :
SET #i := 0;
SET #j := 0.5;
SELECT id, cat_type FROM
(SELECT #i := #i + 1 as ordering, id, cat_type FROM table_name WHERE cat_type = 'free'
UNION
SELECT #j := #j + 2 as ordering, id, cat_type FROM table_name WHERE cat_type = 'paid')
AS base_table
ORDER BY ordering;
Works like charm. Thanks for the answers.
here is my table:
-------------------------
A1 | A2 | count |
-------------------------
a | b | 1 |
b | a | 1 |
c | a | 1 |
d | b | 1 |
b | d | 1 |
-------------------------
i want to select distinct values from this table with distinct count values.If i use to select A2 column where clause i specified using "b" that time i want result like this
A | count
--------------
a | 1
d | 1
I guess this is what you need ,
select distinct(A2) from table1 where count=1
so that you get this output ,
A | count
--------------
a | 1
d | 1
Are you trying to do this:
select A1 as A,count FROM Table1 WHERE A2 = 'b' GROUP BY A1,count
It will give you the result:
A count
a 1
d 1
See SQL Fiddle
I have table structure like below:
id |parent|name |value
1 | 0 | aaa |
2 | 0 | bbb |
3 | 0 | ccc |
4 | 1 | | 111
5 | 1 | | 222
6 | 3 | | 333
I want to display parent if it has child records.
Like:
(parent id + name + value first child)
1 - aaa - 111
3 - ccc - 333
There is no meaning of the first child in the database, you can get the first child by the mininum of the id or the minimum of the value, but the values are not stored with a specific order in the table, so you can't tell which value is the first one.
But, assuming that the id is auto incremental column, then value of the first child is the value of the minimum id, then you can do this:
SELECT
t1.parent,
t2.name,
t1.value
FROM tablename AS t1
INNER JOIN
(
SELECT MIN(id) AS id, parent
FROM tablename
GROUP BY parent
) AS t22 ON t22.id = t1.id AND t1.parent = t22.parent
INNER JOIN tablename AS t2 ON t1.parent = t2.id;
See it in action here:
SQL Fiddle Demo
This will give you :
| PARENT | NAME | VALUE |
-------------------------
| 1 | aaa | 111 |
| 3 | ccc | 333 |
Or: You can get it by the minimum value:
SELECT
t1.parent,
t2.name,
MIN(t1.value) AS value
FROM tablename AS t1
INNER JOIN tablename AS t2 ON t1.parent = t2.id
GROUP BY t1.parent, t2.name;
See it in action:
SQL Fiddle Demo
This will give you:
| PARENT | NAME | VALUE |
-------------------------
| 1 | aaa | 111 |
| 3 | ccc | 333 |