SUM

2016-09-19 71 views
-1

让我们假设这个模式:SUM

CREATE TABLE test 
(
test_Id INT NOT NULL PRIMARY KEY AUTO_INCREMENT, 
user_Id INT NOT NULL, 
date DATE, 
result VARCHAR(255) NOT NULL, 
) engine=innodb; 

我的目标是拿起最后5个结果最高为每个不同的USER_ID,有序从最新到最旧。除此之外,根据结果栏我想计算出最后结果的比例,以便能够以最佳比例提取3个用户。

因此,让我们在这个数据为例:

test_Id | user_Id | date  | result 
1  | 1  |2016-09-05 | A 
2  | 3  |2016-09-13 | A 
3  | 3  |2016-09-30 | A 
4  | 4  |2016-09-22 | A 
5  | 4  |2016-09-11 | C 
6  | 7  |2016-09-18 | D 
7  | 4  |2016-09-08 | B 
8  | 6  |2016-09-20 | E 
9  | 7  |2016-09-16 | A 
10  | 7  |2016-09-29 | E 
11  | 7  |2016-09-23 | A 
12  | 7  |2016-09-16 | B 
13  | 4  |2016-09-15 | B 
14  | 7  |2016-09-07 | C 
15  | 7  |2016-09-09 | A 
16  | 3  |2016-09-26 | A 
17  | 4  |2016-09-11 | C 
18  | 4  |2016-09-30 | E 

我已经能够做到的,是这个查询:

SELECT p.user_Id, p.RowNumber, p.date, p.result, 
     SUM(CASE WHEN p.result='A' OR p.result='B' 
     THEN 1 ELSE 0 END) as avg 
FROM (
    SELECT @row_num := IF(@prev_value=user_Id,@row_num+1,1) 
      AS RowNumber, test_Id, user_Id, date, result, 
      @prev_value := user_Id 
    FROM test, 
    (SELECT @row_num := 1) x, 
    (SELECT @prev_value := '') y 
    WHERE @prev_value < 5 
    ORDER BY user_Id, YEAR(date) DESC, MONTH(date) DESC, 
      DAY(date) DESC 
) p 
WHERE p.RowNumber <=10 
GROUP BY p.user_Id, p.test_Id 
ORDER BY p.user_Id, p.RowNumber; 

该询问提供我这种类型的输出:

RowNumber |test_Id | user_Id | date  | result | avg 
1   | 1  | 1  |2016-09-05 | A  | 1 
1   | 3  | 3  |2016-09-30 | A  | 1 
2   | 16  | 3  |2016-09-26 | A  | 1 
3   | 2  | 3  |2016-09-13 | A  | 1 
1   | 18  | 4  |2016-09-30 | E  | 0 
2   | 4  | 4  |2016-09-22 | A  | 1 
3   | 13  | 4  |2016-09-15 | B  | 1 
4   | 5  | 4  |2016-09-11 | C  | 0 
5   | 17  | 4  |2016-09-11 | C  | 0 
1   | 8  | 6  |2016-09-20 | E  | 0 
1   | 10  | 7  |2016-09-29 | E  | 0 
2   | 11  | 7  |2016-09-23 | A  | 1 
3   | 6  | 7  |2016-09-18 | D  | 0 
4   | 9  | 7  |2016-09-16 | A  | 1 
5   | 12  | 7  |2016-09-16 | B  | 1 

我期待的是,在平均值栏中会得到匹配的每个用户的结果总数条件(A或B值),以便能够根据每个user_id的5个结果计算比率。 (0,0.2,0.4,0.6,0.8,1)。 事情是这样的:在做SUM时

RowNumber |test_Id | user_Id | date  | result | avg 
1   | 1  | 1  |2016-09-05 | A  | 1 
1   | 3  | 3  |2016-09-30 | A  | 3 
2   | 16  | 3  |2016-09-26 | A  | 3 
3   | 2  | 3  |2016-09-13 | A  | 3 
1   | 18  | 4  |2016-09-30 | E  | 2 
2   | 4  | 4  |2016-09-22 | A  | 2 
3   | 13  | 4  |2016-09-15 | B  | 2 
4   | 5  | 4  |2016-09-11 | C  | 2 
5   | 17  | 4  |2016-09-11 | C  | 2 
1   | 8  | 6  |2016-09-20 | E  | 0 
1   | 10  | 7  |2016-09-29 | E  | 3 
2   | 11  | 7  |2016-09-23 | A  | 3 
3   | 6  | 7  |2016-09-18 | D  | 3 
4   | 9  | 7  |2016-09-16 | A  | 3 
5   | 12  | 7  |2016-09-16 | B  | 3 

我是不是由GROUP BY限制p.user_Id,p.test_Id条款?我试着查询只有user_Id作为GROUP BY子句,并且只有test_Id作为GROUP BY子句,而没有得到预期的结果。

+0

你的小组由具有是错误的,看到http://stackoverflow.com/a/39551434 – Drew

+0

使用MySQL 5.5版本。也许你指的是'成果'是一个非'分组'的专栏。无论如何,我喜欢@P.Salmon的方法。 – Dez

+0

你有一个2列的组,而有4个非agg列。这导致垃圾数据结果 – Drew

回答

1

我认为你需要计算平均,然后加入

select a.rn,a.test_id,a.user_id,a.date,a.result,u.avg from 
(
select  t1.* 
     , if (t1.user_id <> @p, @rn:=1,@rn:[email protected]+1) rn 
     , @p:=t1.user_id p 
from  (select @rn:=0, @p:='') rn,test t1 
order by t1.user_id, t1.date desc 
) a 
join 
(
select s.user_id 
      , sum(case when s.result = 'A' or s.result = 'B' then 1 else 0 end) as avg 
from 
(
select  t1.* 
     , if (t1.user_id <> @p, @rn:=1,@rn:[email protected]+1) rn 
     , @p:=t1.user_id p 

from  (select @rn:=0, @p:='') rn,test t1 
order by t1.user_id, t1.date desc 
) s 
where s.rn <= 5 
group by s.user_id 
) u on u.user_id = a.user_id 
where a.rn <= 5 
+0

这种方法对我的目标非常有用,而且性能相当好。为了满足我的需求,我对其进行了一些修改以获取比率和订单结果。非常感谢。 – Dez