Marcus
Marcus

Reputation: 4480

select 1 rand() from each of 4 where clauses mysql

Using MySQL and PHP. I'm trying to select 4 random ads from a table. 1 for adspot 1, 1 for adspot 2, 1 for adspot 3, 1 for adspot 4. Here is what my table looks like:

ad_id | ad_spot | ad_html

1 | 3 | <ad html>
2 | 1 | <ad html>
3 | 4 | <ad html>
4 | 2 | <ad html>

There are about 1200 ads in the table with multiple records for each ad spot and the records can change at anytime. Here is the query I use to select 1 random ad for a specific adspot:

SELECT ad_html FROM ads WHERE ad_spot = '2' ORDER BY RAND() LIMIT 1

I timed a script that selected all 1200 records and put them in a PHP array, then randomly chose 1 for each adspot. That took longer on average than running 4 MySQL queries, with different where clauses, to select the ads with RAND().

What is the most efficient way to combine the following queries into a single query?

SELECT ad_html FROM ads WHERE ad_spot = '1' ORDER BY RAND() LIMIT 1
SELECT ad_html FROM ads WHERE ad_spot = '2' ORDER BY RAND() LIMIT 1
SELECT ad_html FROM ads WHERE ad_spot = '3' ORDER BY RAND() LIMIT 1
SELECT ad_html FROM ads WHERE ad_spot = '4' ORDER BY RAND() LIMIT 1

Upvotes: 3

Views: 228

Answers (2)

Ben English
Ben English

Reputation: 3918

SELECT
   MAX(IF(row_num = 1, ad_html, NULL)) AS 'ad_space_1',
   MAX(IF(row_num = 2, ad_html, NULL)) AS 'ad_space_2',
   MAX(IF(row_num = 3, ad_html, NULL)) AS 'ad_space_3',
   MAX(IF(row_num = 4, ad_html, NULL)) AS 'ad_space_4'
FROM
(
   SELECT
      @row_num := @row_num + 1 AS 'row_num',
      ad_html
   FROM    
      (SELECT  
         @cnt := COUNT(*) + 1,
         @lim := 4,
         @row_num := 0
      FROM
         ads
      ) vars
   STRAIGHT_JOIN
      (
      SELECT
         r.*,
         @lim := @lim - 1
      FROM    
         ads r
      WHERE   
         (@cnt := @cnt - 1)
         AND RAND(203121231) < @lim / @cnt
      ) i
) j

Give it a random seed each query from your php (timestamp or such). Alternatively you could omit the outer query and the inner query will return 4 rows which you can iterate through in your php code.

Upvotes: 1

user1032531
user1032531

Reputation: 26281

ORDER BY RAND() is very inefficient.

What about doing a quick COUNT query, using PHP to use the number and get (4) random numbers, then using those numbers in your query using IN.

Upvotes: 0

Related Questions