problem: find first 2 users have @ least 10 items in category, per category.
table structure:
create table items( id int auto_increment primary key, datetime datetime, category int, user int, items_count int );
sample data:
insert items (datetime, category, user, items_count) values ('2013-01-01 00:00:00', 1, 1, 10), ('2013-01-01 00:00:01', 1, 2, 1), ('2013-01-01 00:00:02', 1, 3, 10), ('2013-01-01 00:00:03', 1, 2, 9), ('2013-01-01 00:00:00', 2, 4, 10), ('2013-01-01 00:00:01', 2, 1, 10), ('2013-01-01 00:00:01', 2, 5, 10);
desired result:
category user 1 1 1 3 2 4 2 5
note: shown in result, need able show preference towards user when multiple users meet requirements simultaneously.
sql fiddle:
http://sqlfiddle.com/#!2/58e60
this have tried:
select derived.*, if (@category != derived.category, @rank := 1, @rank := @rank + 1) rank, @category := category from( select category, user, sum(items_count) items_count, max(datetime) datetime items group category, user having sum(items_count) >= 10 ) derived join(select @rank := 0, @category := 0) r having rank <= 2 order derived.category, derived.datetime
but faulty. not not take user precedence account, produce wrong result data such this:
('2013-01-01 00:00:00', 1, 1, 10), ('2013-01-01 00:00:01', 1, 2, 1), ('2013-01-01 00:00:02', 1, 3, 10), ('2013-01-01 00:00:03', 1, 2, 9), ('2013-01-01 00:00:10', 1, 3, 1);
additional information: not know if procedures make difference in scenario, unfortunately not option either. user running query has select privilege.
in order find users meet needs, need cumulative sum of counts. following query finds occasions when user first reaches 10 units. if counts never negative, there one:
select i.* (select i.*, (select sum(items_count) items i2 i2.user = i.user , i2.category = i.category , i2.datetime <= i.datetime ) cumsum items ) cumsum - items_count < 10 , cumsum >= 10 order datetime; to first two, need use mysql tricks counting within group. here example works:
select i.* (select i.*, if(@prevc = category, @rn := @rn + 1, @rn := 1) rn, @prevc := category (select i.*, (select sum(items_count) items i2 i2.user = i.user , i2.category = i.category , i2.datetime <= i.datetime ) cumsum items ) cross join (select @rn := 0) const cumsum - items_count < 10 , cumsum >= 10 ) rn <= 2 order category, datetime; i have problem approach, because nothing in mysql says expression @prevc := category calculated after calculation rn. however, seems case, , seems work in practice.
Comments
Post a Comment