SELECT random but every name should be selected at least once - mysql

I have a problem in my MySQL query: I have more that 100000 records,
All I want is to select randomly 10 entries where I can see all devices at least once,
Devices names are differents from user to other.
The table has many devices name, the name is in another table where I joined to that table with the device ID
Every user has less than 10 devices so basically I can see all of them in LIMIT 10 but the random function doesn't pick some of them sometimes
I use :
SELECT DISTINCT name,signal
FROM my_table
Where name='any_name'
ORDER BY RAND()LIMIt 10
This selects 10 entries but sometimes some devices are not selected
Example :
+------------+------------+
| Device | Signal |
+------------+------------+
| Router1 | -60 |
| Router2 | -56 |
| Router3 | -102 |
| Router4 | -125 |
| ....... | .... |
+------------+------------+

Try using this code:
SELECT column_name FROM table_name ORDER BY RAND() LIMIT 10
But make sure you have put your column_name and table_name as your intended.
In additional, try to use this link beside:
http://jan.kneschke.de/projects/mysql/order-by-rand/
Good luck.

You can try this (untested). The logic is to select those device records that their signal is the maximum one for that device.
SELECT aa.name, aa.signal
FROM (
SELECT name, MAX(signal) AS max_signal
FROM my_table
GROUP BY name
) AS _aa
INNER JOIN my_table AS aa
ON aa.name = _aa.name
WHERE aa.signal = _aa.max_signal
ORDER BY RAND()
LIMIT 10;

Nasty way of doing it with a sub query on the SELECT:-
SELECT b.Device, (SELECT Signal FROM my_table a WHERE a.Device = b.Device ORDER BY RAND() LIMIT 1)
FROM
(
SELECT DISTINCT Device
FROM my_table
ORDER BY RAND()
LIMIT 10
) b

Related

SQL: Get the most frequent value for each group

Lets say that I have a table ( MS-ACCESS / MYSQL ) with two columns ( Time 'hh:mm:ss' , Value ) and i want to get most frequent value for each group of row.
for example i have
Time | Value
4:35:49 | 122
4:35:49 | 122
4:35:50 | 121
4:35:50 | 121
4:35:50 | 111
4:35:51 | 122
4:35:51 | 111
4:35:51 | 111
4:35:51 | 132
4:35:51 | 132
And i want to get most frequent value of each Time
Time | Value
4:35:49 | 122
4:35:50 | 121
4:35:51 | 132
Thanks in advance
Remark
I need to get the same result of this Excel solution : Get the most frequent value for each group
** MY SQL Solution **
I found a solution(Source) that works fine with mysql but i can't get it to work in ms-access:
select cnt1.`Time`,MAX(cnt1.`Value`)
from (select COUNT(*) as total, `Time`,`Value`
from `my_table`
group by `Time`,`Value`) cnt1,
(select MAX(total) as maxtotal from (select COUNT(*) as total,
`Time`,`Value` from `my_table` group by `Time`,`Value`) cnt3 ) cnt2
where cnt1.total = cnt2.maxtotal GROUP BY cnt1.`Time`
Consider an INNER JOIN to match the two derived table subqueries rather than a list of subquery select statements matched with WHERE clause. This has been tested in MS Access:
SELECT MaxCountSub.`Time`, CountSub.`Value`
FROM
(SELECT myTable.`Time`, myTable.`Value`, Count(myTable.`Value`) AS CountOfValue
FROM myTable
GROUP BY myTable.`Time`, myTable.`Value`) As CountSub
INNER JOIN
(SELECT dT.`Time`, Max(CountOfValue) As MaxCountOfValue
FROM
(SELECT myTable.`Time`, myTable.`Value`, Count(myTable.`Value`) AS CountOfValue
FROM myTable
GROUP BY myTable.`Time`, myTable.`Value`) As dT
GROUP BY dT.`Time`) As MaxCountSub
ON CountSub.`Time` = MaxCountSub.`Time`
AND CountSub.CountOfValue = MaxCountSub.MaxCountOfValue
you can do this by query like this:
select time, value
from (select value, time from your_table
group by value , time
order by count(time) desc
) temp where temp.value = value
group by value

mysql select all rows meeting the first and second lowest values?

I wonder how I could select every user who met the first and second lowest values of a result table?
Table Test
NAME VALUE
John 8
Marie 8
Luis 10
Carlos 10
Leo 13
Max 14
So the result in this case would be
NAME VALUE
John 8
Marie 8
Luis 10
Carlos 10
Thanks a lot!
BTW, I did my home work searching on google and everything, didn't come up with anything but querying the table and then using PHP to filter that for me, not good for performance.
#Aziz I get the error : #1235 - This version of MySQL doesn't yet support 'LIMIT & IN/ALL/ANY/SOME subquery'
Thanks
Thank you all for the load of useful answers!
Just in case falls into funny results like I did, I needed more filters and had to add to the query, here follows:
SELECT * FROM results_temp WHERE
semana='semana6' AND
total_pontos IN (
SELECT * FROM (
SELECT DISTINCT total_pontos
FROM results_temp
WHERE semana='semana6'
ORDER BY `total_pontos`
LIMIT 0,2
) AS t
)
Regards
Try this:
SELECT * FROM Test WHERE `value` IN (
SELECT * FROM (
SELECT DISTINCT `value`
FROM Test
ORDER BY `value`
LIMIT 0,2
) AS t
)
Try this:
SELECT t.*
FROM Test t
INNER JOIN (SELECT DISTINCT t.value FROM Test t ORDER BY t.value LIMIT 2
) A ON t.value = A.value;
Check this SQL FIDDLE DEMO
OUTPUT
| NAME | VALUE |
|--------|-------|
| John | 8 |
| Marie | 8 |
| Luis | 10 |
| Carlos | 10 |
SELECT *
FROM tablename
WHERE
value <= (SELECT MIN(Value)
FROM tablename
WHERE value>(SELECT MIN(VALUE)
FROM tablename))
Please see fiddle here.
The uncorrelated version of a given query is nearly always faster...
SELECT x.*
FROM tablename x
JOIN (SELECT DISTINCT value FROM tablename ORDER BY value LIMIT 2) y
ON y.value = x.value;

select distinct values and order by the same column(value)

I have tried to find something to help me with this, but no luck.
I have a column "slide_no" with values 1-4.
I want to select everything from the database with distinct slide_no order by slide_no but show random selected images.
Database table
slide_id | slide_name | slide_no | fk_project_id
1 | pic1.jpg | 1 | 2
2 | pic2.jpg | 3 | 4
3 | pic3.jpg | 2 | 3
4 | pic4.jpg | 4 | 1
5 | pic5.jpg | 2 | 6
6 | pic6.jpg | 3 | 5
As you can see, the slide_no don't have to be unique, and I want it to be able to show random images on each page load. So far, I have only been able to produce a query that get the first 4 images out.
Is it possible to order by slide_no and get random images, with different (still ordered by slide_no) images?
Thanks in advance.
MySQL provides ORDER BY RAND() for this.
ORDER BY RAND() combined with LIMIT is useful for selecting a random sample from a set of rows.
The query will be:
SELECT *
FROM ( SELECT *
FROM `tblName`
GROUP BY slide_no
ORDER BY RAND()
) `tempTable`
ORDER BY slide_no ASC
You could try something like this if your just looking for a single random ID each time.
SELECT slide_id
FROM {table_name}
ORDER BY RAND()
LIMIT 1;
Working example:
http://www.sqlfiddle.com/#!2/0664c/8
Select slide_name, slide_no From
(SELECT *
FROM ( SELECT *
FROM tableName
GROUP BY slide_no, slide_name
ORDER BY RAND()
) `tempTable`
) x
Group by slide_no
ORDER BY slide_no ASC
limit 4
SELECT slide_no
, ( SELECT TOP 1 slide_name
FROM #tmp T2
WHERE T2.slide_no = T1.slide_no
ORDER BY RAND() --You can place other logic to "randomize" here in the future
)
FROM #tmp T1
GROUP BY slide_no;
I'm not sure if this gives you what you're looking for. The problem is that the repetitive calls of RAND() with the same seed value return the same results. If you want it to be truly random, that's another question in itself. See here for generating a random number in SQL.

Using ORDER BY and GROUP BY together

My table looks like this (and I'm using MySQL):
m_id | v_id | timestamp
------------------------
6 | 1 | 1333635317
34 | 1 | 1333635323
34 | 1 | 1333635336
6 | 1 | 1333635343
6 | 1 | 1333635349
My target is to take each m_id one time, and order by the highest timestamp.
The result should be:
m_id | v_id | timestamp
------------------------
6 | 1 | 1333635349
34 | 1 | 1333635336
And i wrote this query:
SELECT * FROM table GROUP BY m_id ORDER BY timestamp DESC
But, the results are:
m_id | v_id | timestamp
------------------------
34 | 1 | 1333635323
6 | 1 | 1333635317
I think it causes because it first does GROUP_BY and then ORDER the results.
Any ideas? Thank you.
One way to do this that correctly uses group by:
select l.*
from table l
inner join (
select
m_id, max(timestamp) as latest
from table
group by m_id
) r
on l.timestamp = r.latest and l.m_id = r.m_id
order by timestamp desc
How this works:
selects the latest timestamp for each distinct m_id in the subquery
only selects rows from table that match a row from the subquery (this operation -- where a join is performed, but no columns are selected from the second table, it's just used as a filter -- is known as a "semijoin" in case you were curious)
orders the rows
If you really don't care about which timestamp you'll get and your v_id is always the same for a given m_i you can do the following:
select m_id, v_id, max(timestamp) from table
group by m_id, v_id
order by max(timestamp) desc
Now, if the v_id changes for a given m_id then you should do the following
select t1.* from table t1
left join table t2 on t1.m_id = t2.m_id and t1.timestamp < t2.timestamp
where t2.timestamp is null
order by t1.timestamp desc
Here is the simplest solution
select m_id,v_id,max(timestamp) from table group by m_id;
Group by m_id but get max of timestamp for each m_id.
You can try this
SELECT tbl.* FROM (SELECT * FROM table ORDER BY timestamp DESC) as tbl
GROUP BY tbl.m_id
SQL>
SELECT interview.qtrcode QTR, interview.companyname "Company Name", interview.division Division
FROM interview
JOIN jobsdev.employer
ON (interview.companyname = employer.companyname AND employer.zipcode like '100%')
GROUP BY interview.qtrcode, interview.companyname, interview.division
ORDER BY interview.qtrcode;
I felt confused when I tried to understand the question and answers at first. I spent some time reading and I would like to make a summary.
The OP's example is a little bit misleading.
At first I didn't understand why the accepted answer is the accepted answer.. I thought that the OP's request could be simply fulfilled with
select m_id, v_id, max(timestamp) as max_time from table
group by m_id, v_id
order by max_time desc
Then I took a second look at the accepted answer. And I found that actually the OP wants to express that, for a sample table like:
m_id | v_id | timestamp
------------------------
6 | 1 | 11
34 | 2 | 12
34 | 3 | 13
6 | 4 | 14
6 | 5 | 15
he wants to select all columns based only on (group by)m_id and (order by)timestamp.
Then the above sql won't work. If you still don't get it, imagine you have more columns than m_id | v_id | timestamp, e.g m_id | v_id | timestamp| columnA | columnB |column C| .... With group by, you can only select those "group by" columns and aggreate functions in the result.
By far, you should have understood the accepted answer.
What's more, check row_number function introduced in MySQL 8.0:
https://www.mysqltutorial.org/mysql-window-functions/mysql-row_number-function/
Finding top N rows of every group
It does the simlar thing as the accepted answer.
Some answers are wrong. My MySQL gives me error.
select m_id,v_id,max(timestamp) from table group by m_id;
#abinash sahoo
SELECT m_id,v_id,MAX(TIMESTAMP) AS TIME
FROM table_name
GROUP BY m_id
#Vikas Garhwal
Error message:
[42000][1055] Expression #2 of SELECT list is not in GROUP BY clause and contains nonaggregated column 'testdb.test_table.v_id' which is not functionally dependent on columns in GROUP BY clause; this is incompatible with sql_mode=only_full_group_by
Why make it so complicated? This worked.
SELECT m_id,v_id,MAX(TIMESTAMP) AS TIME
FROM table_name
GROUP BY m_id
Just you need to desc with asc. Write the query like below. It will return the values in ascending order.
SELECT * FROM table GROUP BY m_id ORDER BY m_id asc;

Query to Segment Results Based on Equal Sets of Column Value

I'd like to construct a single query (or as few as possible) to group a data set. So given a number of buckets, I'd like to return results based on a specific column.
So given a column called score which is a double which contains:
90.00
91.00
94.00
96.00
98.00
99.00
I'd like to be able to use a GROUP BY clause with a function like:
SELECT MIN(score), MAX(score), SUM(score) FROM table GROUP BY BUCKETS(score, 3)
Ideally this would return 3 rows (grouping the results into 3 buckets with as close to equal count in each group as is possible):
90.00, 91.00, 181.00
94.00, 96.00, 190.00
98.00, 99.00, 197.00
Is there some function that would do this? I'd like to avoid returning all the rows and figuring out the bucket segments myself.
Dave
create table test (
id int not null auto_increment primary key,
val decimal(4,2)
) engine = myisam;
insert into test (val) values
(90.00),
(91.00),
(94.00),
(96.00),
(98.00),
(99.00);
select min(val) as lower,max(val) as higher,sum(val) as total from (
select id,val,#row:=#row+1 as row
from test,(select #row:=0) as r order by id
) as t
group by ceil(row/2)
+-------+--------+--------+
| lower | higher | total |
+-------+--------+--------+
| 90.00 | 91.00 | 181.00 |
| 94.00 | 96.00 | 190.00 |
| 98.00 | 99.00 | 197.00 |
+-------+--------+--------+
3 rows in set (0.00 sec)
Unluckily mysql doesn't have analytical function like rownum(), so you have to use some variable to emulate it. Once you do it, you can simply use ceil() function in order to group every tot rows as you like. Hope that it helps despite my english.
set #r = (select count(*) from test);
select min(val) as lower,max(val) as higher,sum(val) as total from (
select id,val,#row:=#row+1 as row
from test,(select #row:=0) as r order by id
) as t
group by ceil(row/ceil(#r/3))
or, with a single query
select min(val) as lower,max(val) as higher,sum(val) as total from (
select id,val,#row:=#row+1 as row,tot
from test,(select count(*) as tot from test) as t2,(select #row:=0) as r order by id
) as t
group by ceil(row/ceil(tot/3))