选择对行有限制的MAX值 [英] Select MAX value with restriction to rows

查看:80
本文介绍了选择对行有限制的MAX值的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有3张桌子:

比赛日:

matchday_id | season_id | userid | points | matchday
----------------------------------------------------
1           |  1        | 1      | 33     | 1
2           |  1        | 2      | 45     | 1
etc

玩家

userid | username
-----------------
1      | user1
2      | user2
etc.

季节

seasons_id  | title  | userid
----------------------------
1           | 2011   | 3
2           | 2012   | 10
3           | 2013   | 5

我的查询:

SELECT s.title, p.username, SUM(points) FROM matchdays m
INNER JOIN players p ON p.userid = m.userid
INNER JOIN seasons s ON m.userid = s.userid
group by s.season_id

这导致(示例!):

title | username | SUM(points)
------------------------------
2011  | user3    | 3744
2012  | user10   | 3457
2013  | user5    | 3888

应该是一张表,其中列出每个赛季的获胜者(最高分).目前,标题和用户名是正确的,但是总和太高了.我不知道算出了什么总和.理想情况下,总和是每个用户每个季节的每个比赛日的总和.

What it should look like is a table with the winner (max points) of every season. Right now, the title and username is correct, but the sum of the points is way too high. I couldn't figure out what sum is calculated. Ideally, the sum is the addition of every matchday of a season for every user.

推荐答案

您的主要问题是仅按季节分组.因此,无论哪个球员,您的SUM都在一个赛季的所有积分上运行.

Your main issue is that you group by seasons only. Thus your SUM is running on all points over a season, regardless of the player.

无论如何,整个方法都是错误的.在季节表中具有用户标识的缺陷"是最大的问题,您似乎也知道. 我将向您说明如何一次一次计算数据库中的排名,并随时让他们使用,这将为您节省很多麻烦,并且显然也节省了一些CPU和加载时间.

首先创建一个新表"Rankings":

The whole approach is wrong anyway. The "flaw" with userid in the season table is your biggest issue, and you seem to know it. I will explain you how to calculate your rankings in the database one time for all, and to have them at your disposal at all times, which will save you a lot of headaches, and obviously save some CPU and loading times as well.

CREATE table rankings (season_id INT, userid INT, points INT, rank INT)

如果您有很多玩家,请为除points

If you have a lot of players, index all columns but points

这是一个单发操作,每个季节结束时都要运行. 因此,暂时来说,每个季节您必须运行几次.

This is a oneshot operation to run each time a season has ended. So for the time being, you will have to run it several times for each season.

关键是计算每个球员在赛季中的排名,这是必不可少的,以后将非常有用.因为MySQL没有为此提供窗口功能,所以我们必须使用一个古老的技巧:增加一个计数器.

The key here is to compute the rank of each player for the season, which is a must-have that will be super-handy for later. Because MySQL doesnt have a window function for that, we have to use an old trick : incrementing a counter.

我分解.

这将计算一个赛季的得分,并提供该赛季的排名:

This will compute the points of a season, and provide the ranking for that season:

SELECT season_id, userid, SUM(points) as points 
FROM matchdays
WHERE season_id = 1
GROUP BY season_id, userid
ORDER BY points DESC

现在,我们调整此查询以添加一个排名列:

Now we adapt this query to add a rank column :

SELECT
   season_id, userid, points,
   @curRank := @curRank + 1 AS rank
FROM
(   
    SELECT season_id, userid, SUM(points) as points 
    FROM matchdays
    WHERE season_id = 1
    GROUP BY season_id, userid
)   T, 
(
    SELECT @curRank := 0
) R
ORDER BY T.points DESC

就是这样. 现在,我们可以将计算结果插入到我们的排名表中,以永久存储一次:

That's it. Now we can INSERT the results of this computation into our ranking table, to store it once for good :

INSERT INTO rankings
SELECT
   season_id, userid, points,
   @curRank := @curRank + 1 AS rank
FROM
(   
    SELECT season_id, userid, SUM(points) as points 
    FROM matchdays
    WHERE season_id = 1
    GROUP BY season_id, userid
)   T, 
(
    SELECT @curRank := 0
) R
ORDER BY T.points DESC

更改season_id = 1,然后每个季节重复一次. 将此查询保存在某个地方,以后,每当一个季节结束,就运行一次.

Change the season_id = 1 and repeat for each season. Save this query somewhere, and in the future, run it once each time a season has ended.

现在,您拥有适当的数据库计算排名和漂亮的排名表,可以随时查询.

Now you have a proper database-computed ranking and a nice ranking table that you can query whenever you want.

您想要每个赛季的胜利者吗?就这么简单:

You want the winner for each season ? As simple as that:

SELECT S.title, P.username, R.points
FROM Ranking R
INNER JOIN seasons S ON R.season_id=S.season_id
INNER JOIN players P ON R.userid=P.userid
WHERE R.rank = 1

随着时间的流逝,您会发现您可以通过排名表非常简单地完成很多不同的事情.

You will discover over the time that you can do a lot of different things very simply with your ranking table.

这篇关于选择对行有限制的MAX值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆