Hallo и хорошее воскресенье для всех. Мне нужно выбрать N случайных записей из каждой группы.Выберите N случайных записей в группе
Начиная с запроса Quassnoi
http://explainextended.com/2009/03/01/selecting-random-rows/
выбрать X случайную запись, которую я написал эту процедуру магазин
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 ;
, что я помню, таким образом, чтобы дать вам идею:
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);
Моя проблема заключается в том, что Quassnoi query, даже t hough очень эффективен, он занимает ровно 1 секунду на большом рекордере. Поэтому, если я применяю его в моем sp несколько раз, общее время увеличивается.
Можете ли вы предложить мне лучший способ решить мою проблему? Заранее благодарен
EDIT.
create table `prova` (
`id` int(11) not null auto_increment,
`id_gruppo` int(11) default null,
`prog` int(11) default null,
primary key (`id`)
) engine=myisam charset=latin1;
delimiter //
drop procedure if exists inserisci //
create procedure inserisci(in quanti int)
begin
declare i int default 0;
while i < quanti do
insert into prova (id_gruppo,prog) values (
(floor(1 + (rand() * 100))),
(floor(1 + (rand() * 30)))
);
set i = i + 1;
end while;
end //
delimiter ;
call inserisci(1000000);
@Clodoaldo: Моя хранимая процедура
call casualipergruppo('prova','id_gruppo',2);
дает мне 200 записей и занимает около 23 секунд. Ваша хранимая процедура продолжает давать мне код ошибки: 1473 Слишком высокий уровень вложенности для выбора, даже если я увеличиваю значение varchar до 20000. Я не знаю, существует ли ограничение на союзы, участвующие в запросе.
@nick Вы попробовали это? Любая проблема? –
Привет, Clodoaldo. Прежде всего, спасибо за то, что вы посвятили меня. +1 только для этого. Извините за задержку моего ответа. Я пробовал ваш sp на столе с 1 миллионом записей и 100 различными группами. Sp дает мне эту ошибку «Слишком высокий уровень гнездования для выбора» –
My sp очень медленный (около 25 секунд), но, по крайней мере, возвращает мне правильный результат. –