Reputation: 4480
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
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
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