对应行的汇总功能

时间:2018-11-06 16:18:57

标签: postgresql group-by aggregate-functions

我有一个下表,其中包含idts的组合主键以实现历史记录:

create table "author" (
  "id"     bigint     not null,
  "ts"     timestamp  not null default now(),
  "login"  text       unique not null,
  primary key ("id", "ts")
);

现在,我只对最新的login值感兴趣。因此,我按id分组:

select "id", max("ts"), "login" from "author" group by "id";

但这会引发错误:聚合函数中应使用login

idmax("ts")唯一地标识一行,因为连音符(id,ts)是​​主键。我需要loginidmax("ts")所标识的行匹配。

我可以写一个子选择来找到login

select ao."id", max(ao."ts"), 
       (select ai.login from "author" ai
        where ao."id" = ai."id" and max(ao."ts") = ai.ts)
from "author" ao
group by "id";

这是可行的,但是它很嘈杂并且不是很聪明,因为它可以搜索整个表,尽管搜索组就足够了。

是否存在一个聚合函数,该函数避免了子选择,而是给了我剩下的login,它们属于idmax("ts")

1 个答案:

答案 0 :(得分:1)

您必须标识正确的密钥才能从表中获取所需的值。

正确的密钥是:

    ##main loop

man = player (100,430,100,100)
bullet = bullets (50,50)
game = True

idle = [(py.transform.scale(idle[0],(man.width,man.lenght))),(py.transform.scale(idle[1],(man.width,man.lenght))),(py.transform.scale(idle[2],(man.width,man.lenght))),(py.transform.scale(idle[3],(man.width,man.lenght))),(py.transform.scale(idle[4],(man.width,man.lenght))),(py.transform.scale(idle[5],(man.width,man.lenght))),(py.transform.scale(idle[6],(man.width,man.lenght))),(py.transform.scale(idle[7],(man.width,man.lenght))),(py.transform.scale(idle[8],(man.width,man.lenght))),(py.transform.scale(idle[9],(man.width,man.lenght)))]
run_right = [(py.transform.scale(run_right[0],(man.width,man.lenght))),(py.transform.scale(run_right[1],(man.width,man.lenght))),(py.transform.scale(run_right[2],(man.width,man.lenght))),(py.transform.scale(run_right[3],(man.width,man.lenght))),(py.transform.scale(run_right[4],(man.width,man.lenght))),(py.transform.scale(run_right[5],(man.width,man.lenght))),(py.transform.scale(run_right[6],(man.width,man.lenght))),(py.transform.scale(run_right[7],(man.width,man.lenght)))]
jump = [(py.transform.scale(jump[0],(man.width,man.lenght))),(py.transform.scale(jump[1],(man.width,man.lenght))),(py.transform.scale(jump[2],(man.width,man.lenght))),(py.transform.scale(jump[3],(man.width,man.lenght))),(py.transform.scale(jump[4],(man.width,man.lenght))),(py.transform.scale(jump[5],(man.width,man.lenght))),(py.transform.scale(jump[6],(man.width,man.lenght))),(py.transform.scale(jump[7],(man.width,man.lenght))),(py.transform.scale(jump[8],(man.width,man.lenght))),(py.transform.scale(jump[9],(man.width,man.lenght)))]
run_left = [(py.transform.flip(run_right[0],True,False)),(py.transform.flip(run_right[1],True,False)),(py.transform.flip(run_right[2],True,False)),(py.transform.flip(run_right[3],True,False)),(py.transform.flip(run_right[4],True,False)),(py.transform.flip(run_right[5],True,False)),(py.transform.flip(run_right[6],True,False)),(py.transform.flip(run_right[7],True,False))]
idle2 = [(py.transform.flip(idle[0],True,False)),(py.transform.flip(idle[1],True,False)),(py.transform.flip(idle[2],True,False)),(py.transform.flip(idle[3],True,False)),(py.transform.flip(idle[4],True,False)),(py.transform.flip(idle[5],True,False)),(py.transform.flip(idle[6],True,False)),(py.transform.flip(idle[7],True,False)),(py.transform.flip(idle[8],True,False)),(py.transform.flip(idle[9],True,False))]
jump2 = [(py.transform.flip(jump[0],True,False)),(py.transform.flip(jump[1],True,False)),(py.transform.flip(jump[2],True,False)),(py.transform.flip(jump[3],True,False)),(py.transform.flip(jump[4],True,False)),(py.transform.flip(jump[5],True,False)),(py.transform.flip(jump[6],True,False)),(py.transform.flip(jump[7],True,False)),(py.transform.flip(jump[8],True,False)),(py.transform.flip(jump[9],True,False))]
shoot_idle = [(py.transform.scale(shoot_idle[0],(man.width,man.lenght))),(py.transform.scale(shoot_idle[1],(man.width,man.lenght))),(py.transform.scale(shoot_idle[2],(man.width,man.lenght))),(py.transform.scale(shoot_idle[3],(man.width,man.lenght)))]
shoot_idle2 = [(py.transform.flip(shoot_idle[0],True,False)),(py.transform.flip(shoot_idle[1],True,False)),(py.transform.flip(shoot_idle[2],True,False)),(py.transform.flip(shoot_idle[3],True,False))]
pows = [(py.transform.scale(pows[0],(bullet.width,bullet.lenght))),(py.transform.scale(pows[1],(bullet.width,bullet.lenght))),(py.transform.scale(pows[2],(bullet.width,bullet.lenght))),(py.transform.scale(pows[3],(bullet.width,bullet.lenght))),(py.transform.scale(pows[4],(bullet.width,bullet.lenght)))]
pows2 = [(py.transform.flip(pows[0],True,False)),(py.transform.flip(pows[1],True,False)),(py.transform.flip(pows[2],True,False)),(py.transform.flip(pows[3],True,False)),(py.transform.flip(pows[4],True,False))]


while game:
    clock.tick (30)

    for event in py.event.get():
        if event == py.QUIT:
            game = False

    keys = py.key.get_pressed ()



    if keys[py.K_RIGHT] and man.x <= 700:
        man.x += man.vel
        man.right = True
        man.left = False
        man.standing = False
        man.idlecount = 0
        man.direction = 1

    elif keys[py.K_LEFT] and man.x >= 0:
        man.x -= man.vel
        man.right = False
        man.left = True
        man.standing = False
        man.idlecount = 0
        man.direction = -1

    elif keys [py.K_SPACE]:
        if man.direction == 1:
            bullet.x = man.x + 75
            bullet.y = man.y + 20
            man.shooting = True
            bullet.shoot = True

        elif man.direction == -1:
            bullet.x = man.x - 25
            bullet.y = man.y + 20
            man.shooting = True
            bullet.shoot = True


    else:
        man.standing = True
        man.shooting = False

    if not(man.jumping):
        if keys[py.K_UP]:
            man.jumping = True
            man.right = False
            man.left = False
            man.standing = False
            man.walkcount = 0
    else:
        if man.jumpcount >= -14:
            neg = 1
            if man.jumpcount < 0:
                neg = -1
            man.y -= (man.jumpcount ** 2) * 0.2 * neg
            man.jumpcount -= 1
        else:
            man.jumping = False
            man.jumpcount = 14


    drawGameScreen ()

并使用它来获取所需的登录名:

 select "id", max("ts") from "author" group by "id";

或者使用窗口函数:

 select a1."id", a1.ts, a1.login
 from "author" a1
      inner join (select "id", max("ts") maxts, "login" from "author" group by "id") a2
      ON a1.id = a2.id AND a1.ts = a2.maxts;

还有其他几种方法可以给这只猫剥皮,但这基本上就是要点。