Question

I want to run a query like this, so that I will always get 20 results, even if the 1st SELECT statement does not have enough data to return 10 results.

(
SELECT t.column1, t.column2
FROM table t 
WHERE t.status = 1 
LIMIT 10
)
UNION
(
SELECT t.column1, t.column2 
FROM table t
WHERE t.status = 2 
LIMIT 20 
)
LIMIT 20 

But I then want to ORDER BY RAND() and make sure that all the available results from the first SELECT statement are included in the final result set.

When I add ORDER BY RAND() to the end of this query, it gives me result sets that do not include all 10 results from the first SELECT, I assume because it is really getting 30 rows and then choosing 20 at random from the 30.

Any ideas would be appreciated.

Here is what worked for me:

SELECT x.*
FROM ((
SELECT t.column1, t.column2
FROM table t 
WHERE t.status = 1 
LIMIT 10
)
UNION
(
SELECT t.column1, t.column2 
FROM table t
WHERE t.status = 2 
LIMIT 20 
)
LIMIT 20) x
ORDER BY RAND
Was it helpful?

Solution

Should work if you order your UNION results by what SELECT they are “from” first, before the LIMIT 20 is applied:

SELECT … FROM
(
  (
    SELECT t.column1, t.column2, 0 AS ordervalue FROM … WHERE …
    LIMIT 10
  )
  UNION
  (
    SELECT t.column1, t.column2, 1 FROM … WHERE …
    LIMIT 20 
  )
  ORDER BY ordervalue ASC # this will make the values from your first SELECT come
                          # first, then the ones from the second

  LIMIT 20 # of those ordered values, the first 20 are taken
)
ORDER BY RAND()

I introduced a static value as ordervalue here – in your special case it would not be necessary, since you select by status 1 or 2, so you could order by that value directly. But if that was not the case (or the status values would be different), that “pseudo” column value would be the way to go.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top