Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Tags:

php

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
like image 853
Marcus Avatar asked Dec 04 '25 16:12

Marcus


1 Answers

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.

like image 147
Ben English Avatar answered Dec 06 '25 05:12

Ben English



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!