我正在研究的SQL挑战是构建一个查询来显示一个人的名字以及他们在一列中超过10次迭代数据的平均表现以及他们在下一列中平均超过50次迭代的数据。当然按名称分组。迭代按顺序进行,因此个人过去10的平均值将是该个体的10个最高ID号的平均分数。原始数据集如下所示:
ID, Name, Score
1, Joe, 10
2, Bob, 13
3, Joe, 9
4, Kim, 6
5, Rob, 8
6, Han, 9
7, Kim, 12
这样大约有1000行,大约有50个名字。最终目标是运行一个返回如下内容的查询:
Name, AvgPast10, AvgPast50
Bob, 8, 10
Joe, 7, 9
Kim, 6, 10
Han, 9, 6
Rob, 7, 5
当我尝试这样做时,我意识到可能有不同的方法来做到这一点。也许自我联合回到自己,也许是嵌套的select语句。我试过并意识到我正在进入我的脑海。此外,我的老板是查询优化的真正坚持者。出于某种原因,他鄙视嵌套的select语句。如果我需要它们,那么我最好有一个令人信服的理由,或者至少对如何在查询中构建优化有所了解。
答案 0 :(得分:1)
不可否认,这个使用嵌套的select(或子查询):
SELECT Name, AVG(CASE WHEN Rank <= 10 THEN Score END) AvgPast10,
AVG(CASE WHEN Rank <= 50 THEN Score END) AvgPast50
FROM (
SELECT Name,
@rank := IF(@Name = Name, @rank+1, 1) as Rank,
@Name := Name, Score
FROM tbl
ORDER BY Name, ID DESC
) A
GROUP BY Name
为了简单起见,请参阅使用过去3和过去5的 Demo 。
答案 1 :(得分:0)
你的样本非常小,所以我在下面使用了2和50,但希望无论数字或平均数是多少,这个过程都是明确的
| NAME | AVG_2 | AVG_50 |
|------|-------|--------|
| Bob | 13 | 13 |
| Han | 9 | 9 |
| Joe | 9 | 9.5 |
| Kim | 12 | 9 |
| Rob | 8 | 8 |
SELECT
name
, sum_2 / (count_2 * 1.0) AS avg_2
, sum_50 / (count_50 * 1.0) AS avg_50
FROM (
SELECT
name
, COUNT(CASE
WHEN rn <= 2 THEN score END) count_2
, SUM(CASE
WHEN rn <= 2 THEN score END) sum_2
, COUNT(CASE
WHEN rn <= 50 THEN score END) count_50
, SUM(CASE
WHEN rn <= 50 THEN score END) sum_50
FROM (
SELECT
*
, ROW_NUMBER() OVER (PARTITION BY name ORDER BY ID DESC) AS rn
FROM Scores
) x
GROUP BY
name
) y
ORDER BY
name
如果观察次数小于所需数量(例如,计数为20但平均值为50),我不确定您想要做什么,我在本例中使用了实际计数。