Ciao a tutti e buona domenica.
Come da titolo mi trovo a dover risolvere il problema della selezione di un tot numero di record da ciascun gruppo in modo casuale.

Mi son guardato un pò intorno e ho trovato questo thread:

http://forums.mysql.com/read.php?10,...130#msg-274130

La soluzione fornita da laptop alias è impraticabile su grosse tabelle.

Per quel che riguarda la selezione casuale di record, la soluzione più efficiente che abbia trovato finora è questa qui:

http://explainextended.com/2009/03/0...g-random-rows/

Partendo da quella query ho creato questa stored procedure:

codice:
delimiter //
drop procedure if exists casualiPerGruppo //
create procedure casualiPerGruppo(in tabella varchar(50),in campo varchar(50),in numPerGruppo int)
comment 'Selezione di N record casuali per gruppo'
begin
declare elenco_campi varchar(255);
declare valore int;
declare finite int default 0;
declare query1 varchar(250);
declare query2 varchar(250);
declare query3 varchar(250);
declare query4 varchar(250);
declare cur_gruppi cursor for select gruppo from tmp_view;
declare continue handler for not found set finite = 1;

drop table if exists tmp_casuali;
set @query1 = concat('create temporary table tmp_casuali like ', tabella);
prepare stmt from @query1;
execute stmt;
deallocate prepare stmt;

set @query2 = concat('create or replace view tmp_view as select ',campo,' as gruppo from ',tabella,' group by ',campo);
prepare stmt from @query2;
execute stmt;
deallocate prepare stmt;

open cur_gruppi;
mio_loop:loop
fetch cur_gruppi into valore;
	if finite = 1 then
		leave mio_loop;
	end if;

set @query3 = concat("select group_concat(column_name) into @elenco_campi
		      from information_schema.columns
                      where table_name = '",tabella,"' and table_schema = database()");
prepare stmt from @query3;
execute stmt;
deallocate prepare stmt;

set @query4 = concat('insert into tmp_casuali select ',
		     @elenco_campi,' from (
				     select  @cnt := count(*) + 1,
				     @lim :=', numPerGruppo,
			             ' from ',tabella,
				     ' where ',campo,' = ', valore,
				     ' ) vars
				     straight_join
					(
					select  r.*,
					@lim := @lim - 1
					from ', tabella, ' r
					where   (@cnt := @cnt - 1)
					and rand() < @lim / @cnt and ', campo, ' = ', valore ,
					') i');

prepare stmt from @query4;
execute stmt;
deallocate prepare stmt;

end loop;
close cur_gruppi;
select * from tmp_casuali;
end //
delimiter ;
che poi richiamo così:

codice:
create table prova (
id int not null auto_increment primary key,
id_gruppo int,
altro varchar(10)
) engine = myisam;


insert into prova (id_gruppo,altro) values 
(1,'aaa'),(2,'bbb'),(3,'ccc'),(1,'ddd'),(1,'eee'),(2,'fff'),
(2,'ggg'),(2,'hhh'),(3,'iii'),(3,'jjj'),(3,'kkk'),(1,'lll'),(4,'mmm');

call casualiPerGruppo('prova','id_gruppo',2);
La query di Quassnoi per quanto geniale e performante, su qualche milione di record mi richiede anche più di un secondo. Se poi vado a richiamarla più volte sui vari gruppi i tempi logicamente si allungano ulteriormente.

Qual è secondo voi il miglior approccio a questo problema?
Grazie a tutti.