N 个结果的子查询结果的 SUM 作为每个用户的最大值
SUM from the results of a subquery of N results as max for each user
让我们假设这个架构:
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;
我的目标是为每个不同的 user_Id 选择最后 5 个结果作为最大值,从最新到最旧排序。除此之外,根据结果列,我想计算那些最后结果的比率,以便能够选择具有最佳比率的 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
我期望的是,在 avg 列中会得到每个用户符合条件(A 或 B 值)的总结果,以便能够从每个 [ 的 5 个结果中计算出一个比率=36=]。 (0、0.2、0.4、0.6、0.8、1)。
像这样:
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
我做SUM的时候是不是被GROUP BY p.user_Id, p.test_Id子句限制了?我尝试了仅使用 user_Id 作为 GROUP BY 子句并且仅使用 test_Id 作为 GROUP BY 子句的查询,但没有得到预期的结果。
我认为你需要计算平均然后加入
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:=@rn+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:=@rn+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
让我们假设这个架构:
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;
我的目标是为每个不同的 user_Id 选择最后 5 个结果作为最大值,从最新到最旧排序。除此之外,根据结果列,我想计算那些最后结果的比率,以便能够选择具有最佳比率的 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
我期望的是,在 avg 列中会得到每个用户符合条件(A 或 B 值)的总结果,以便能够从每个 [ 的 5 个结果中计算出一个比率=36=]。 (0、0.2、0.4、0.6、0.8、1)。 像这样:
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
我做SUM的时候是不是被GROUP BY p.user_Id, p.test_Id子句限制了?我尝试了仅使用 user_Id 作为 GROUP BY 子句并且仅使用 test_Id 作为 GROUP BY 子句的查询,但没有得到预期的结果。
我认为你需要计算平均然后加入
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:=@rn+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:=@rn+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