我正在尝试将大量card game次比赛(总是有3位玩家)保存到PotsgreSQL 8.4.9中
我几乎所有的东西(请在下面)只缺少2个小部件。
我创建了3个SQL表:
create table pref_users (
uid varchar(32) primary key,
first_name varchar(64),
female boolean,
avatar varchar(128)
}
create table pref_games {
gid serial,
rounds integer not null,
finished timestamp default current_timestamp
}
create table pref_scores (
uid varchar(32) references pref_users,
gid serial references pref_games, /* XXX serial ok here? */
money integer not null,
quit boolean
);
这是我的PL / pgSQL程序,我需要一些帮助:
create or replace function pref_insert_scores(
_uid0 varchar, _money0 integer, _quit0 boolean,
_uid1 varchar, _money1 integer, _quit1 boolean,
_uid2 varchar, _money2 integer, _quit2 boolean,
_rounds integer) returns void as $BODY$
begin
insert into pref_games (rounds) values (_rounds);
-- XXX how do I get the _gid of this new game?
insert into pref_scores (uid, gid, money, quit)
values(_uid0, _gid, _money0, _quit0);
insert into pref_scores (uid, gid, money, quit)
values(_uid1, _gid, _money1, _quit1);
insert into pref_scores (uid, gid, money, quit)
values(_uid2, _gid, _money2, _quit2);
end;
$BODY$ language plpgsql;
然后我需要一些帮助来加入第一张桌子中的first_name,女性,头像数据的分数 - 这样我就可以在网页的表格中显示最近7天玩过的游戏列表:
01.12.2011 Alice $10 Bob $20 Charlie -$30 17 rounds
01.12.2011 Alice $0 (quit) Bob $20 Charlie -$20 5 rounds
更新
由于 mu太短的帮助我现在我的桌子上装满了数据,但仍然无法弄清楚如何列出玩家所执行的所有游戏 - 以及他的2个对手和他们的分数。
我有一张包含所有比赛的表格:
# select * from pref_games limit 5;
gid | rounds | finished
-----+--------+----------------------------
1 | 10 | 2011-10-26 14:10:35.46725
2 | 12 | 2011-10-26 14:34:13.440868
3 | 12 | 2011-10-26 14:34:39.279883
4 | 14 | 2011-10-26 14:35:25.895376
5 | 14 | 2011-10-26 14:36:56.765978
然后我在这里参加了第3场比赛的所有3名球员(以及他们的分数):
# select * from pref_scores where gid=3;
uid | gid | money | quit
-----------------------+-----+-------+------
OK515337846127 | 3 | -37 | f
OK40798070412 | 3 | -75 | f
MR2871175175044094219 | 3 | 112 | f
这些都是玩家用uid = DE9411玩的游戏:
# select * from pref_scores where id='DE9411';
uid | gid | money | quit
--------+-----+-------+------
DE9411 | 43 | 64 | f
DE9411 | 159 | -110 | f
DE9411 | 224 | 66 | f
DE9411 | 297 | -36 | f
DE9411 | 385 | 29 | f
DE9411 | 479 | -40 | f
DE9411 | 631 | -14 | f
DE9411 | 699 | 352 | f
DE9411 | 784 | -15 | f
DE9411 | 835 | 242 | f
但是如何在上述结果集中列出其他2名球员及其得分?
答案 0 :(得分:1)
您不希望serial
中的pref_scores
,只需int
:
create table pref_scores (
uid varchar(32) references pref_users,
gid int references pref_games, /* XXX serial ok here? */
money integer not null,
quit boolean
);
您想使用INSERT ... RETURNING ... INTO
:
create or replace function pref_insert_scores(
_uid0 varchar, _money0 integer, _quit0 boolean,
_uid1 varchar, _money1 integer, _quit1 boolean,
_uid2 varchar, _money2 integer, _quit2 boolean,
_rounds integer) returns void as $BODY$
declare
_gid int;
begin
insert into pref_games (rounds) values (_rounds) returning gid into _gid;
-- etc...
答案 1 :(得分:1)
此查询应该适用于使用当前架构获取所需的列表。然而,有这么多连接,性能可能不会那么大。由于您知道您总是有3个用户,因此根据此表的预期大小,您可能希望测试具有单个游戏表的性能,并将用户的信息去规范化。
select g.finished, u1.uid u1, s1.money m1, s1.quit q1, u2.uid u2, s2.money m2, s2.quit
q2, u3.uid u3, s3.money m3, s3.quit q3, g.rounds
from pref_games g
inner join pref_scores s1 on s1.gid = g.gid
inner join pref_scores s2 on s2.gid = g.gid and s2.uid > s1.uid
inner join pref_scores s3 on s3.gid = g.gid and s3.uid > s2.uid
inner join pref_users u1 on s1.uid = u1.uid
inner join pref_users u2 on s2.uid = u2.uid
inner join pref_users u3 on s3.uid = u3.uid
and g.finished > CURRENT_DATE - interval '1 week'
答案 2 :(得分:0)
在行中:
finished timestamp default current_timestamp
我强烈建议使用
finished timestamptz default current_timestamp
因为实际的日期/时间存储在GMT中,所以允许更加明智的日期/时间算术,因为实际的日期/时间存储在GMT中 - 它也更适合国际化。
从pg9.1.1手册'8.5。日期/时间类型':
[...]
注意:SQL标准要求只写时间戳等同于没有时区的时间戳,PostgreSQL会尊重这种行为。 (7.3之前的版本将其视为带时区的时间戳。)timestamptz被接受为带时区的时间戳的缩写;这是一个PostgreSQL扩展。
[...]
对于带时区的时间戳,内部存储的值始终为UTC(通用协调时间,传统上称为格林威治标准时间,GMT)。具有指定显式时区的输入值将使用该时区的适当偏移量转换为UTC。如果输入字符串中未指定时区,则假定它位于系统时区参数指示的时区中,并使用时区区域的偏移量转换为UTC。
当输出带有时区值的时间戳时,它始终从UTC转换为当前时区区域,并在该区域中显示为本地时间。要查看另一个时区的时间,请更改时区或使用AT TIME ZONE构造(参见第9.9.3节)。
[...]
答案 3 :(得分:0)
gid serial references pref_games, /* XXX serial ok here? */
这里你应该使用'int'而不是'serial' - 因为你需要在pref_games中引用一个非常具体的记录。