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:
che poi richiamo così: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 ;
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.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);
Qual è secondo voi il miglior approccio a questo problema?
Grazie a tutti.

Rispondi quotando
