LIMIT then RAND rather than RAND then LIMIT - mysql

I'm using full text search to pull rows.
I order the rows based on score (ORDER BY SCORE) , then of the top 20 rows (LIMIT 20), I want to rand (RAND) the result set.
So for any specific search term, I want to randomly show 5 of the top 20 results.
My workaround is code based- where I put the top 20 into an array then randomly select 5.
Is there sql way to do this?

You can do this using an inner select. Select the top twenty rows in the inner select. In the outer select order these rows randomly and select the top five:
SELECT *
FROM (
SELECT *
FROM table1
ORDER BY score DESC
LIMIT 20
) AS T1
ORDER BY RAND()
LIMIT 5

Related

I need to select top five and bottom five numbers from a list of 60 numbers

I need to select top five and bottom five numbers from a list of 60 numbers based on their count.
I have a table - scores
query to select top five
SELECT * FROM scores ORDER BY count DESC LIMIT 5
gets the top five
SELECT * FROM scores ORDER BY count ASC LIMIT 5
gets both sets of numbers -
what would be the best way to combine these two queries to return one set (make these into one query)
join?
I have tried this but get an error on the order by
SELECT * FROM scores order by count desc limit 5 union all select * from scores order by count asc limit 3
You can use UNION ALL:
(SELECT *
FROM scores
ORDER BY count DESC LIMIT 5)
UNION ALL
(SELECT *
FROM scores
ORDER BY count ASC LIMIT 5)

LIMIT by random number between 1 and 10

Essentially, I want to return X number of records from the last 21 days, with an upper limit of 10 records.
How do I add a random LIMIT to a query in MySQL?
Here's my query, with X for the random number 1-10.
SELECT releases.id, COUNT(charts_extended.release_id) as cnt FROM releases
INNER JOIN charts_extended
ON charts_extended.release_id=releases.id
WHERE DATEDIFF(NOW(), releases.date) < 21
GROUP BY releases.id
ORDER BY RAND()
LIMIT 0, X
I tried using RAND() * 10 + 1, but it gives a syntax error.
Is there any way to do this using pure SQL; ie without using an application language to "build" the query as a string and have the application language fill in X programmatically?
Eureka...
In pseudo code:
execute a query to select 10 random rows
select from that assigning a row number 0-9 using a user defined variable to calculate that
cross join with a single hit on rand() to create a number 0-9 and select all rows with row number less than or equal to that number
Here's the essence of the solution (you can adapt your query to work with it:
select * from (
select *, (#row := coalesce(#row + 1, 0)) row from (
// your query here, except simply LIMIT 10
select * from mytable
order by rand()
limit 10
) x
) y
cross join (select rand() * 10 rand) z
where row <= rand
See SQLFiddle. Run it a few times and you'll see you get 1-10 random rows.
If you don't want to see the row number, you can change the outer select * to select only the specific columns from the inner query that you want in your result.
Your query is correct but you need to update limit clause.
$query = "SELECT releases.id, COUNT(charts_extended.release_id) as cnt FROM releases
INNER JOIN charts_extended
ON charts_extended.release_id=releases.id
WHERE DATEDIFF(NOW(), releases.date) < 21
GROUP BY releases.id
ORDER BY RAND()
LIMIT 0,".rand(1,10);
and then execute this query.

Get random rows if full text result is less than N rows

I am using below code to find something
SELECT * FROM table
WHERE MATCH(title) AGAINST('php tutorial') LIMIT 25
If there are titles that match my query, It returns 25 rows. If the row is empty or if less than 25 rows I want to get random 25 rows from table. Is it possible in a single query?
Instead, use order by and limit:
SELECT *
FROM table
ORDER BY MATCH(title) AGAINST('php tutorial') DESC
LIMIT 25
Note that this could be much more expensive, depending on the size of your data because the entire table needs to be sorted.
A more efficient method would be:
select t.*
from ((select t.*, MATCH(title) AGAINST('php tutorial') as score
from table t
where MATCH(title) AGAINST('php tutorial')
limit 25
) union all
(select g.*, -1 as score
from table g
where NOT (MATCH(title) AGAINST('php tutorial'))
limit 25
)
) t
order by score desc
limit 25;
This limits the overall sorting to at most 50 records. Like your original query, it does not guarantee the highest scoring titles will be returned.

How can I limit query's results without using LIMIT

I need to show ordered 20 records on my grid but I can't use LIMIT because of my generator(Scriptcase) using LIMIT to show lines per page. It's generator's bug but I need to solve it for my project. So is it possible to show 20 ordered record from my table with a query?
As from comments,if you can't use limit then you can rank your results on basis of some order and in parent select filter limit the results by rank number
select * from (
select *
,#r:=#r + 1 as row_num
from your_table_name
cross join (select #r:=0)t
order by some_column asc /* or desc*/
) t1
where row_num <= 20
Demo with rank no.
Another hackish way would be using group_concat() with order by to get the list of ids ordered on asc/desc and substring_index to pick the desired ids like you need 20 records then join with same table using find_in_set ,But this solution will be very expensive in terms of performance and group_concat limitations if you need more than 20 records
select t.*
from your_table_name t
join (
select
substring_index(group_concat(id order by some_column asc),',',20) ids_list
from your_table_name
) t1 on (find_in_set(t.id , t1.ids_list) > 0)
Demo without rank
What about SELECT in SELECT:
SELECT *
FROM (
-- there put your query
-- with LIMIT 20
) q
So outer SELECT is without LIMIT and your generator can add own.
In a Scriptcase Grid, you CAN use Limit. This is a valid SQL query that selects only the first 20 records from a table. The grid is set to show only 10 records per page, so it will show 20 results split in a total of 2 pages:
SELECT
ProductID,
ProductName
FROM
Products
LIMIT 20
Also the embraced query works out well:
SELECT
ProductID,
ProductName
FROM
(SELECT
ProductID,
ProductName
FROM Products LIMIT 20) tmp

How do I select the 1st row from a selection of 10 random rows

Lets say I have a 1000 rows in my table.
I want to select 10 of those at random.
SELECT * FROM table ORDER BY RAND() LIMIT 10
Then I want to select the row in that result with the highest value for number
SELECT * FROM table ORDER BY number DESC LIMIT 1
Can anyone help me come up with an efficient way of doing this?
Just use a subquery:
SELECT *
FROM (
SELECT * FROM table ORDER BY RAND() LIMIT 10
)
ORDER BY number DESC LIMIT 1