简体   繁体   English

在SQL查询中出现MAX()和`group by`的问题

[英]Problem with MAX() and `group by` in an SQL query

I'm writing a particularly troublesome query. 我正在编写一个特别麻烦的查询。 It boils down to this: 归结为:

I obtain a table of the structure: 我获得了一个结构表:

pid | tid | points

after a pretty large query. 经过一个非常大的查询。

For ease of explanation: 为便于说明:

  • pid = problem id pid =问题ID
  • tid = team id tid =团队ID
  • points = points awarded to that team for that problem. points =针对该问题授予该团队的积分。

I want to find the team who has scored max points for a particular pid. 我想找到为特定pid获得最高分的球队。

My question is twofold: 我的问题是双重的:

  1. If this were a simple table that went by the name teampoints , how do I get the tid that has MAX(points) for every pid? 如果这是一个名为teampoints的简单表格,我如何获得每个pid具有MAX(点数)的tid I tried SELECT pid, tid, MAX(points) from teampoints group by pid; 我用SELECT pid, tid, MAX(points) from teampoints group by pid;尝试了SELECT pid, tid, MAX(points) from teampoints group by pid; but understandably, that would not work 但可以理解,那是行不通的

  2. I've arrived at this result after a rather large query. 经过一次相当大的查询,我得到了这个结果。 If the answer to my first involves selecting data from teampoints again, is there any way to do that without having to calculate the whole table again? 如果我的第一个答案涉及再次从teampoints选择数据,有没有办法做到这一点,而无需再次计算整个表?

Thanks 谢谢

PS: I use mysql. PS:我用的是mysql。


GORY DETAILS: TREAD WITH CAUTION GORY DETAILS:小心谨慎

I have a few tables in my system, their relevant structures being: 我的系统中有几个表,它们的相关结构是:

users: uid
teams: tid | eid | teamname
teammembers: tid | uid
events: eid
problems: pid | eid
submissions: subid | pid | uid | eid | points | subts

Some notes: - problems belong to events - users belong to teams - submissions belong to problems(pid) and users(uid). 一些注意事项: - 问题属于事件 - 用户属于团队 - 提交属于问题(pid)和用户(uid)。 the submissions table has a redundant eid field, which can always be determined from the pid. 提交表有一个冗余的eid字段,它总是可以从pid中确定。

The use case is: 用例是:

  • users form teams. 用户组成团队。 users are identified by uid , teams by tid . 用户由uid ,团队通过tid识别。 Team members are stored in teammembers table. 团队成员存储在teammembers表中。
  • users can make submissions, which are stored in submissions table. 用户可以提交提交,这些提交存储在提交表中。 submissions are awarded points. 提交被授予积分。 subts is the unix timestamp of when the submission was made. subts是提交提交时的unix时间戳。
  • users can submit multiple times for the same problem. 用户可以针对同一问题多次提交。 the latest submission (max subts) is counted. 计算最新提交的内容(最大子文件)。

now, in this set up I want to find the teamname that has scored maximum points for any given event (eid). 现在,在这个成立我想找到teamname已经拿下最高points对于任何给定的事件(EID)。

I hope this makes my situation clear. 我希望这能使我的情况变得清晰。 I wanted to ask only what I needed to know. 我只想问我需要知道什么。 I furnish these details up an a request in the comments. 我在评论中提出了这些细节。

EDIT: the query that generated the teampoints table is: 编辑:生成teampoints表的查询是:

SELECT s.pid, teamlatest.tid, s.points 
  FROM  submissions s, teammembers tm, teams t, 
      (SELECT max(maxts) AS maxts, pid, tid 
         FROM (SELECT latest.maxts, latest.pid, t.tid 
                 FROM submissions s, teams t, teammembers tm,
                     (SELECT max(subts) AS maxts, pid, uid 
                        FROM submissions 
                        WHERE eid=3 AND status='P' 
                        GROUP BY pid, uid
                     ) AS latest
                 WHERE s.uid=latest.uid 
                   AND s.pid=latest.pid 
                   AND s.subts=latest.maxts 
                   AND latest.uid=tm.uid 
                   AND tm.tid=t.tid 
                   AND t.eid=3
              ) AS latestbyteam
         GROUP BY pid, tid) AS teamlatest
  WHERE s.pid=teamlatest.pid 
    AND teamlatest.tid=t.tid 
    AND t.tid=tm.tid 
    AND tm.uid=s.uid 
    AND s.subts=teamlatest.maxts
  1. One way: 单程:

     SELECT pid, tid, points FROM teampoints WHERE (pid, points) IN ( SELECT pid, MAX(points) FROM teampoints GROUP BY pid ) 

    Another, using joins: 另一个,使用连接:

     SELECT s1.* FROM teampoints AS s1 LEFT JOIN teampoints AS s2 ON s1.pid = s2.pid AND s1.points < s2.points WHERE s2.tid IS NULL 
  2. You can INSERT INTO a temporary table for the complex query: 您可以INSERT INTO复杂查询的临时表:

     CREATE TEMPORARY TABLE scores ( pid INT, tid INT, points INT, KEY pp (pid, points) ); INSERT INTO scores (pid, tid, points) SELECT <a complex query> 

    then SELECT the top scorers from that. 然后从中选择最佳得分手。

select pid, tid, points
from teampoints tp
where not exists (
    select 1
    from teampoints tp1
    where tp.pid = tp1.pid
    and tp.points < tp1.points)

or somesuch .... 或者某些......

You could store the results of your first query in a temporary table and try something like this 您可以将第一个查询的结果存储在临时表中并尝试这样的操作

SELECT  pid, tid, points
FROM    teampoints tp
        INNER JOIN (
          SELECT    pid, points = MAX(points) 
          FROM      teampoints 
          GROUP BY  pid
        ) tp_max ON tp_max.pid = tp.pid AND tp_max.points = tp.points

Note that you will get doubles when two teams have equal points on a project. 请注意,当两个团队在项目中具有相同的分数时,您将获得双倍的分数。

If you would post your query, it would be easier for us trying to optimize it io trying to invent it all over. 如果你要发布你的查询,我们会更容易尝试优化它,我试图发明它。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM