If I understand it well -- you need n
images. If possible from different products. Otherwise, several images from the same product is acceptable as fallback.
From now, the only solution I could think of, is to build a temporary table, with numbered rows such as there will be one "image" of each product at the "top" -- and filed with the rest of the images.
Once that table is build, your query is just a SELECT ... LIMIT n
.
This will perform horribly -- and if you choose that solution of something inspired -- you should consolidate the image table off-line or on schedule basis.
see http://sqlfiddle.com/#!2/81274/2
--
-- test values
--
create table P (id int, title char(20));
insert into P values
(1, "product 1"),
(2, "product 2"),
(3, "product 3");
create table I (pid int, filename char(40));
insert into I values
(1, "image p1-1"),
(1, "image p1-2"),
(3, "image p3-1"),
(3, "image p3-2"),
(3, "image p3-3");
--
-- "ordered" image table
--
create table T(n int primary key auto_increment not null,
filename char(20));
--
-- consolidate images (once in a while)
--
delete from T;
insert into T(filename)
select filename from I group by pid;
insert into T(filename)
select filename from I order by rand();
--
-- do the actual query
--
select * from T limit n;
EDIT Here is a completely different idea. Not using a consolidation table/view -- so this might be seen as better:
http://sqlfiddle.com/#!2/57ea9/4
select distinct(filename) from
(select 1 as p, filename from I group by pid
union (select 2 as p, filename from I order by rand() limit 3)) as T
order by p limit 3
The key point here is I don't have to really "number" the rows. Only to keep track of which rows are coming from the first SELECT
. That is the purpose of p
. I set both LIMIT
clause to the same value for simplicity. I don't think you have to "optimize" that part since the benefit would be very small -- and ORDER BY RAND()
is so terrible that you don't have to think about "performances" here ;)
Please note I don't have fully tested this solution. Let me know if there is some corner cases (well.. any case) that don't work.