Обсуждение: Saving score of 3 players into a table

Поиск
Список
Период
Сортировка

Saving score of 3 players into a table

От
Alexander Farber
Дата:
Hello,

I'm trying to save results of card game with 3 players into a table.

It is bad enough, that I had to introduce
3 columns for user ids: id0, id1, id2 and
3 columns for their scores: money0, money1, money2 -

        create table pref_results (
                id0 varchar(32) references pref_users,
                id1 varchar(32) references pref_users,
                id2 varchar(32) references pref_users,
                money0 integer not null,
                money1 integer not null,
                money2 integer not null,
                rounds integer not null,
                finished timestamp default current_timestamp
        );

But now I've also realized, that I don't know,
how to join that table with the pref_users,
so that I get first_name for each of 3 players -

        $sth = $db->prepare("
        select
             id0,
             id1,
             id2,
             money0,
             money1,
             money2,
             rounds,
             to_char(finished,'DD.MM.YYYY') as day
        from pref_results
        where finished > now() - interval '1 week'
             and (id0=? or id1=? or id2=?)
       ");
        $sth->execute(array($id, $id, $id));

        while ($row = $sth->fetch(PDO::FETCH_ASSOC)) {
               # XXX print the table with day, first_names and money
        }

I'm probably doing something wrong here?

Thank you
Alex

Re: Saving score of 3 players into a table

От
"David Johnston"
Дата:
-----Original Message-----
From: pgsql-general-owner@postgresql.org
[mailto:pgsql-general-owner@postgresql.org] On Behalf Of Alexander Farber
Sent: Tuesday, October 25, 2011 3:33 PM
To: pgsql-general
Subject: [GENERAL] Saving score of 3 players into a table

Hello,

I'm trying to save results of card game with 3 players into a table.

It is bad enough, that I had to introduce
3 columns for user ids: id0, id1, id2 and
3 columns for their scores: money0, money1, money2 -

        create table pref_results (
                id0 varchar(32) references pref_users,
                id1 varchar(32) references pref_users,
                id2 varchar(32) references pref_users,
                money0 integer not null,
                money1 integer not null,
                money2 integer not null,
                rounds integer not null,
                finished timestamp default current_timestamp
        );

But now I've also realized, that I don't know, how to join that table with
the pref_users, so that I get first_name for each of 3 players -


[...]

I'm probably doing something wrong here?

Thank you
Alex

--------------------/Original Message ----------

Yes, you are creating multiple columns to hold data for each of the players.
Each player should go into a separate row.

You want something like:

CREATE TABLE pref_results (
    Game_id varchar,
    Player_id varchar,
    Player_winnings numeric,
    Player_position integer -- not truly required but useful for
generating columns later
);

CREATE TABLE pref_games (
    Game_id varchar,
    Game_rounds integer,
    Game_finished_ts timestamptz
);

It is almost always wrong to have columns where you are simply adding a
sequential integer to the same base name.

However, to answer your question, you would need to JOIN the "pref_users"
table to the "pref_results" table THREE TIMES, once for each of (id0, id1,
id2).

SELECT *
FROM pref_results
JOIN pref_users user_0 ON (id0 = user_0.id)
JOIN perf_users user_1 ON (id1 = user_1.id)
JOIN perf_users user_2 ON (id1 = user_2.id)

Note the aliases for the pref_users table, and you would want to alias any
columns you end up pulling into the SELECT list.

Then you hope you never need to add a 4th player.

If you still want to present the data using 3 sets of columns for the
players you would need to perform a limited self-join:

SELECT
Game_id,
p1.Player_id AS P1_ID,
p2.Player_id AS P2_ID,
p3.Player_id AS P3_ID
FROM (SELECT ... FROM pref_results WHERE Player_position = 1) p1 USING
(Game_id)
JOIN (SELECT .. FROM pref_results WHERE Player_position = 2) p2 USING
(Game_id)
JOIN (SELECT .. FROM pref_results WHERE Player_position = 3) p2 USING
(Game_id)

Then add whatever columns and JOIN you need to get all the desired fields
into the output.

In this way you have a database model that is easy to query and insert data
into while still having the ability to view the data in a natural way
(horizontally).  Add should you want to track a game with four players you
can still use the same data model and simply add a VIEW similar to the
three-person view but with a fourth set of columns for the fourth player.

David J.




Re: Saving score of 3 players into a table

От
Michael Glaesemann
Дата:
On Oct 25, 2011, at 15:32, Alexander Farber wrote:

> Hello,
>
> I'm trying to save results of card game with 3 players into a table.
>
> It is bad enough, that I had to introduce
> 3 columns for user ids: id0, id1, id2 and
> 3 columns for their scores: money0, money1, money2 -
>
>        create table pref_results (
>                id0 varchar(32) references pref_users,
>                id1 varchar(32) references pref_users,
>                id2 varchar(32) references pref_users,
>                money0 integer not null,
>                money1 integer not null,
>                money2 integer not null,
>                rounds integer not null,
>                finished timestamp default current_timestamp
>        );
>
> But now I've also realized, that I don't know,
> how to join that table with the pref_users,
> so that I get first_name for each of 3 players -
>
>        $sth = $db->prepare("
>        select
>             id0,
>             id1,
>             id2,
>             money0,
>             money1,
>             money2,
>             rounds,
>             to_char(finished,'DD.MM.YYYY') as day
>        from pref_results
>        where finished > now() - interval '1 week'
>             and (id0=? or id1=? or id2=?)
>       ");
>        $sth->execute(array($id, $id, $id));
>
>        while ($row = $sth->fetch(PDO::FETCH_ASSOC)) {
>               # XXX print the table with day, first_names and money
>        }
>
> I'm probably doing something wrong here?

Likely. Are you only ever going to have three players per table? Seems unlikely.

Without knowing anything else about your application, I suspect you need more tables:
a games table
a games_players table with each row associating a single player with a game. A three-player game has three rows per
game.A four-player game would have four. 

Depending on your app, you might also have finished_games and game_player_results tables.

Michael Glaesemann
grzm seespotcode net


Re: Saving score of 3 players into a table

От
Gavin Flower
Дата:
On 26/10/11 08:32, Alexander Farber wrote:
> Hello,
>
> I'm trying to save results of card game with 3 players into a table.
>
> It is bad enough, that I had to introduce
> 3 columns for user ids: id0, id1, id2 and
> 3 columns for their scores: money0, money1, money2 -
>
>          create table pref_results (
>                  id0 varchar(32) references pref_users,
>                  id1 varchar(32) references pref_users,
>                  id2 varchar(32) references pref_users,
>                  money0 integer not null,
>                  money1 integer not null,
>                  money2 integer not null,
>                  rounds integer not null,
>                  finished timestamp default current_timestamp
>          );
>
> But now I've also realized, that I don't know,
> how to join that table with the pref_users,
> so that I get first_name for each of 3 players -
>
>          $sth = $db->prepare("
>          select
>               id0,
>               id1,
>               id2,
>               money0,
>               money1,
>               money2,
>               rounds,
>               to_char(finished,'DD.MM.YYYY') as day
>          from pref_results
>          where finished>  now() - interval '1 week'
>               and (id0=? or id1=? or id2=?)
>         ");
>          $sth->execute(array($id, $id, $id));
>
>          while ($row = $sth->fetch(PDO::FETCH_ASSOC)) {
>                 # XXX print the table with day, first_names and money
>          }
>
> I'm probably doing something wrong here?
>
> Thank you
> Alex
>
You may want to cosider:
finished > CURRENT_DATE - interval '1 week'


Re: Saving score of 3 players into a table

От
Gavin Flower
Дата:
On 26/10/11 08:32, Alexander Farber wrote:
> Hello,
>
> I'm trying to save results of card game with 3 players into a table.
>
> It is bad enough, that I had to introduce
> 3 columns for user ids: id0, id1, id2 and
> 3 columns for their scores: money0, money1, money2 -
>
>          create table pref_results (
>                  id0 varchar(32) references pref_users,
>                  id1 varchar(32) references pref_users,
>                  id2 varchar(32) references pref_users,
>                  money0 integer not null,
>                  money1 integer not null,
>                  money2 integer not null,
>                  rounds integer not null,
>                  finished timestamp default current_timestamp
>          );
>
> But now I've also realized, that I don't know,
> how to join that table with the pref_users,
> so that I get first_name for each of 3 players -
>
>          $sth = $db->prepare("
>          select
>               id0,
>               id1,
>               id2,
>               money0,
>               money1,
>               money2,
>               rounds,
>               to_char(finished,'DD.MM.YYYY') as day
>          from pref_results
>          where finished>  now() - interval '1 week'
>               and (id0=? or id1=? or id2=?)
>         ");
>          $sth->execute(array($id, $id, $id));
>
>          while ($row = $sth->fetch(PDO::FETCH_ASSOC)) {
>                 # XXX print the table with day, first_names and money
>          }
>
> I'm probably doing something wrong here?
>
> Thank you
> Alex
>
Hi,

I agree with the othet replies that you should have the results in
separate tables, but I have tested out something similar to what you
want below.

First, couple of points to note:
(1)  the interval logic you have, selects finish times within one week
of the current date and time.  So if you run it at 11 am, then you miss
records at 10 am 7 days ago, but pick up records that finish at 11:30am
on that day!
(2) I changed the format of the date since numerically there is
sometimes ambiguity between dd.mm.yyyy and mm.dd.yyyy as American use
the latter (9/11 is November 9th to me, but to an American it is
September 11th)
(3) I have used an explicity money type
(4) I suggest that date/times should be stored in the database in GMT,
so that the dates can be dislayed appropriately in any l,ocale, hence
the use of 'timstamptz' (timestamp with timezone).

CREATE TABLE player
(
     id          int PRIMARY KEY,
     first_name  text NOT NULL,
     last_name   text NOT NULL,
     UNIQUE (first_name, last_name)
);


CREATE TABLE pref_results
(
     id          int PRIMARY KEY,
     rounds      int NOT NULL,
     finished    timestamptz NOT NULL,
     player0_id  int NOT NULL REFERENCES player(id),
     money0      money NOT NULL,
     player1_id  int NOT NULL REFERENCES player(id),
     money1      money NOT NULL,
     player2_id  int NOT NULL REFERENCES player(id),
     money2      money NOT NULL,
     CONSTRAINT player0_player1_same CHECK (player0_id != player1_id),
     CONSTRAINT player1_player2_same CHECK (player1_id != player2_id),
     CONSTRAINT player2_player0_same CHECK (player2_id != player0_id)

);


SELECT
     (SELECT first_name FROM player WHERE player.id = pr.player0_id) AS
player0,
     (SELECT first_name FROM player WHERE player.id = pr.player1_id) AS
player1,
     (SELECT first_name FROM player WHERE player.id = pr.player2_id) AS
player2,
     pr.money0,
     pr.money1,
     pr.money2,
     pr.rounds,
     pr.finished,
     to_char(pr.finished,'DD-MON-YYYY') as day
FROM
     pref_results pr
WHERE
     pr.finished > now() - interval '1 week'
ORDER BY
     pr.finished,
     pr.rounds;


Cheers,
Gavin

Re: Saving score of 3 players into a table

От
Alexander Farber
Дата:
Hello again,

thank you for your replies. If I create a separate table for games:

    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
    );

then how do I find the new game id after I've just created it here:

    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;

Thank you! I've listed few more details at
http://stackoverflow.com/questions/7899995/save-scores-of-3-players-per-game-into-postgresql

Regards
Alex

Re: Saving score of 3 players into a table

От
Alban Hertroys
Дата:
On 26 October 2011 10:08, Alexander Farber <alexander.farber@gmail.com> wrote:

>    create table pref_games {
>            gid serial,
>            rounds integer not null,
>            finished timestamp default current_timestamp
>    }

> then how do I find the new game id after I've just created it here:
>
>    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?

Use insert .. returning gid with a cursor:

declare
   game_cur cursor (n integer) for insert into pref_games (rounds)
values (n) returning gid;
   _rec record;
begin
    for _rec in  game_cur(_rounds) loop
        insert into pref_scores (uid, _rec.gid, money, quit) values...
    end loop;


>            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;
>
> Thank you! I've listed few more details at
> http://stackoverflow.com/questions/7899995/save-scores-of-3-players-per-game-into-postgresql
>
> Regards
> Alex
>
> --
> Sent via pgsql-general mailing list (pgsql-general@postgresql.org)
> To make changes to your subscription:
> http://www.postgresql.org/mailpref/pgsql-general
>



--
If you can't see the forest for the trees,
Cut the trees and you'll see there is no forest.

Re: Saving score of 3 players into a table

От
Alexander Farber
Дата:
Hello again,

still I can't figure out how to perform a join
to fetch all games where a player has participated -
I have a table containing all games played:

# 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

And I have a table with scores of each of 3 players:

# select * from pref_scores where gid=3;
          id           | gid | money | quit
-----------------------+-----+-------+------
 OK515337846127        |   3 |   -37 | f
 OK40798070412         |   3 |   -75 | f
 MR2871175175044094219 |   3 |   112 | f

(Which means 3 players have played game #3
and 1 has won 112, while 2 have lost 37 + 75)

My problem is: I'd like to list all games played
by 1 player, with all participants and scores listed.

I'm trying (these are all games played by DE9411):

# select * from pref_scores where id='DE9411';
   id   | 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

Then I'm trying to join with pref_games:

# select s.id, s.gid, s.money, s.quit, to_char(g.finished,
'DD.MM.YYYY') as day from pref_scores s, pref_games g where
s.gid=g.gid and s.id='DE9411';
   id   | gid | money | quit |    day
--------+-----+-------+------+------------
 DE9411 |  43 |    64 | f    | 26.10.2011
 DE9411 | 159 |  -110 | f    | 26.10.2011
 DE9411 | 224 |    66 | f    | 26.10.2011
 DE9411 | 297 |   -36 | f    | 26.10.2011
 DE9411 | 385 |    29 | f    | 26.10.2011
 DE9411 | 479 |   -40 | f    | 26.10.2011
 DE9411 | 631 |   -14 | f    | 26.10.2011
 DE9411 | 699 |   352 | f    | 26.10.2011
 DE9411 | 784 |   -15 | f    | 26.10.2011
 DE9411 | 835 |   242 | f    | 26.10.2011

But how do I display the 2 other players and
their scores in the above result set?

(More info on my problem:
http://stackoverflow.com/questions/7899995/save-scores-of-3-players-per-game-into-postgresql
)

Thank you
Alex

Re: Saving score of 3 players into a table

От
"David Johnston"
Дата:
-----Original Message-----
From: pgsql-general-owner@postgresql.org
[mailto:pgsql-general-owner@postgresql.org] On Behalf Of Alexander Farber
Sent: Wednesday, October 26, 2011 4:16 PM
Cc: pgsql-general
Subject: Re: [GENERAL] Saving score of 3 players into a table

Hello again,

still I can't figure out how to perform a join to fetch all games where a
player has participated - I have a table containing all games played:

# 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

And I have a table with scores of each of 3 players:

# select * from pref_scores where gid=3;
          id           | gid | money | quit
-----------------------+-----+-------+------
 OK515337846127        |   3 |   -37 | f
 OK40798070412         |   3 |   -75 | f
 MR2871175175044094219 |   3 |   112 | f

(Which means 3 players have played game #3 and 1 has won 112, while 2 have
lost 37 + 75)

My problem is: I'd like to list all games played by 1 player, with all
participants and scores listed.

I'm trying (these are all games played by DE9411):

# select * from pref_scores where id='DE9411';
   id   | 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

Then I'm trying to join with pref_games:

# select s.id, s.gid, s.money, s.quit, to_char(g.finished,
'DD.MM.YYYY') as day from pref_scores s, pref_games g where s.gid=g.gid and
s.id='DE9411';
   id   | gid | money | quit |    day
--------+-----+-------+------+------------
 DE9411 |  43 |    64 | f    | 26.10.2011
 DE9411 | 159 |  -110 | f    | 26.10.2011
 DE9411 | 224 |    66 | f    | 26.10.2011
 DE9411 | 297 |   -36 | f    | 26.10.2011
 DE9411 | 385 |    29 | f    | 26.10.2011
 DE9411 | 479 |   -40 | f    | 26.10.2011
 DE9411 | 631 |   -14 | f    | 26.10.2011
 DE9411 | 699 |   352 | f    | 26.10.2011
 DE9411 | 784 |   -15 | f    | 26.10.2011
 DE9411 | 835 |   242 | f    | 26.10.2011

But how do I display the 2 other players and their scores in the above
result set?

(More info on my problem:
http://stackoverflow.com/questions/7899995/save-scores-of-3-players-per-game
-into-postgresql
)

Thank you
Alex

--
Sent via pgsql-general mailing list (pgsql-general@postgresql.org) To make
changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-general


--------- /Original Message ---------------

SELECT *
FROM pref_scores
WHERE gid IN ( SELECT gid FROM pref_games WHERE id = 'DE9411' );

-- Note, "EXISTS" may be faster for large datasets but "IN", at least to me,
is much easier to understand.

In this case you want all scores for games in which person 'DE9411' was a
player.

David J.




Re: Saving score of 3 players into a table

От
Michael Glaesemann
Дата:
On Oct 26, 2011, at 16:15, Alexander Farber wrote:

> Hello again,
>
> still I can't figure out how to perform a join
> to fetch all games where a player has participated -
> I have a table containing all games played:
>
> # 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
>
> And I have a table with scores of each of 3 players:
>
> # select * from pref_scores where gid=3;
>          id           | gid | money | quit
> -----------------------+-----+-------+------
> OK515337846127        |   3 |   -37 | f
> OK40798070412         |   3 |   -75 | f
> MR2871175175044094219 |   3 |   112 | f
>
> (Which means 3 players have played game #3
> and 1 has won 112, while 2 have lost 37 + 75)
>
> My problem is: I'd like to list all games played
> by 1 player, with all participants and scores listed.

Get games for a particular user:

SELECT g.gid, g.rounds, g.finished
  FROM pref_games g
  JOIN pref_scores u USING (gid)
  WHERE u.id = :id;

Now, add the participants for those games

SELECT g.gid, g.rounds, g.finished,
       p.id, p.money, p.quit
  FROM pref_games g
  JOIN pref_scores u USING (gid)
  JOIN pref_scores p USING (gid)
  WHERE u.id = :id;

Michael Glaesemann
grzm seespotcode net


Re: Saving score of 3 players into a table

От
Alexander Farber
Дата:
Thank you Michal and others -

On Wed, Oct 26, 2011 at 11:11 PM, Michael Glaesemann
<grzm@seespotcode.net> wrote:
> Get games for a particular user:
>
> SELECT g.gid, g.rounds, g.finished
>  FROM pref_games g
>  JOIN pref_scores u USING (gid)
>  WHERE u.id = :id;
>
> Now, add the participants for those games
>
> SELECT g.gid, g.rounds, g.finished,
>       p.id, p.money, p.quit
>  FROM pref_games g
>  JOIN pref_scores u USING (gid)
>  JOIN pref_scores p USING (gid)
>  WHERE u.id = :id;
>

I don't know what kind of JOIN that is (above) - but it works well:

#  SELECT g.gid, g.rounds, g.finished,
      p.id, p.money, p.quit
 FROM pref_games g
 JOIN pref_scores u USING (gid)
 JOIN pref_scores p USING (gid)
 WHERE u.id = 'DE9411';
 gid  | rounds |          finished          |           id           |
money | quit
------+--------+----------------------------+------------------------+-------+------
   43 |     12 | 2011-10-26 14:57:54.045975 | OK510649006288         |  -240 | f
   43 |     12 | 2011-10-26 14:57:54.045975 | DE9411                 |    64 | f
   43 |     12 | 2011-10-26 14:57:54.045975 | OK355993104857         |   176 | f
  159 |     19 | 2011-10-26 15:55:54.650444 | DE9396                 |    70 | f
  159 |     19 | 2011-10-26 15:55:54.650444 | DE9411                 |  -110 | f
  159 |     19 | 2011-10-26 15:55:54.650444 | OK5409550866           |    42 | f
  224 |     16 | 2011-10-26 16:27:20.996753 | DE9396                 |     4 | f
  224 |     16 | 2011-10-26 16:27:20.996753 | DE9411                 |    66 | f
  224 |     16 | 2011-10-26 16:27:20.996753 | OK5409550866           |   -70 | f
  297 |     20 | 2011-10-26 17:05:53.514124 | OK486555355432         |  -114 | f
  297 |     20 | 2011-10-26 17:05:53.514124 | DE9411                 |   -36 | f
  297 |     20 | 2011-10-26 17:05:53.514124 | OK5409550866           |   148 | f
  385 |     20 | 2011-10-26 17:43:44.473597 | OK486555355432         |   245 | f
  385 |     20 | 2011-10-26 17:43:44.473597 | DE9411                 |    29 | f
  385 |     20 | 2011-10-26 17:43:44.473597 | OK5409550866           |  -275 | f
  479 |     19 | 2011-10-26 18:26:05.00712  | OK486555355432         |    30 | f
  479 |     19 | 2011-10-26 18:26:05.00712  | DE9411                 |   -40 | f
  479 |     19 | 2011-10-26 18:26:05.00712  | OK5409550866           |     8 | f

but now I'm lost even more - how to JOIN this with
the pref_users table containing first_name, city for each player:

#  select first_name, female, avatar, city
from pref_users where id = 'DE9411';
 first_name | female |           avatar            |   city
------------+--------+-----------------------------+----------
 GRAF63     | f      | picture-9411-1299771547.jpg | ALCORCON

I'm trying:

# SELECT g.gid, g.rounds, g.finished,
      p.id, p.money, p.quit,
      i.first_name, i.avatar
 FROM pref_games g
 JOIN pref_scores u USING (gid)
 JOIN pref_scores p USING (gid)
 JOIN pref_users i USING (id)
 WHERE u.id = 'DE9411';

ERROR:  common column name "id" appears more than once in left table

Another try:

# SELECT g.gid, g.rounds, g.finished,
      p.id, p.money, p.quit,
      i.first_name, i.avatar
 FROM pref_games g, pref_users i
 JOIN pref_scores u USING (gid)
 JOIN pref_scores p USING (gid)
 WHERE u.id = 'DE9411' and p.id=i.id;

ERROR:  column "gid" specified in USING clause does not exist in left table

Regards
Alex

Re: Saving score of 3 players into a table

От
"David Johnston"
Дата:
-----Original Message-----
From: pgsql-general-owner@postgresql.org
[mailto:pgsql-general-owner@postgresql.org] On Behalf Of Alexander Farber
Sent: Thursday, October 27, 2011 7:21 AM
Cc: pgsql-general
Subject: Re: [GENERAL] Saving score of 3 players into a table

Thank you Michal and others -

On Wed, Oct 26, 2011 at 11:11 PM, Michael Glaesemann <grzm@seespotcode.net>
wrote:
> Get games for a particular user:
>
> SELECT g.gid, g.rounds, g.finished
>  FROM pref_games g
>  JOIN pref_scores u USING (gid)
>  WHERE u.id = :id;
>
> Now, add the participants for those games
>
> SELECT g.gid, g.rounds, g.finished,
>       p.id, p.money, p.quit
>  FROM pref_games g
>  JOIN pref_scores u USING (gid)
>  JOIN pref_scores p USING (gid)
>  WHERE u.id = :id;
>

I don't know what kind of JOIN that is (above) - but it works well:

#  SELECT g.gid, g.rounds, g.finished,
      p.id, p.money, p.quit
 FROM pref_games g
 JOIN pref_scores u USING (gid)
 JOIN pref_scores p USING (gid)
 WHERE u.id = 'DE9411';
 gid  | rounds |          finished          |           id           |
money | quit
------+--------+----------------------------+------------------------+------
-+------
   43 |     12 | 2011-10-26 14:57:54.045975 | OK510649006288         |  -240
| f
   43 |     12 | 2011-10-26 14:57:54.045975 | DE9411                 |    64
| f
   43 |     12 | 2011-10-26 14:57:54.045975 | OK355993104857         |   176
| f
  159 |     19 | 2011-10-26 15:55:54.650444 | DE9396                 |    70
| f
  159 |     19 | 2011-10-26 15:55:54.650444 | DE9411                 |  -110
| f
  159 |     19 | 2011-10-26 15:55:54.650444 | OK5409550866           |    42
| f
  224 |     16 | 2011-10-26 16:27:20.996753 | DE9396                 |     4
| f
  224 |     16 | 2011-10-26 16:27:20.996753 | DE9411                 |    66
| f
  224 |     16 | 2011-10-26 16:27:20.996753 | OK5409550866           |   -70
| f
  297 |     20 | 2011-10-26 17:05:53.514124 | OK486555355432         |  -114
| f
  297 |     20 | 2011-10-26 17:05:53.514124 | DE9411                 |   -36
| f
  297 |     20 | 2011-10-26 17:05:53.514124 | OK5409550866           |   148
| f
  385 |     20 | 2011-10-26 17:43:44.473597 | OK486555355432         |   245
| f
  385 |     20 | 2011-10-26 17:43:44.473597 | DE9411                 |    29
| f
  385 |     20 | 2011-10-26 17:43:44.473597 | OK5409550866           |  -275
| f
  479 |     19 | 2011-10-26 18:26:05.00712  | OK486555355432         |    30
| f
  479 |     19 | 2011-10-26 18:26:05.00712  | DE9411                 |   -40
| f
  479 |     19 | 2011-10-26 18:26:05.00712  | OK5409550866           |     8
| f

but now I'm lost even more - how to JOIN this with the pref_users table
containing first_name, city for each player:

#  select first_name, female, avatar, city from pref_users where id =
'DE9411';
 first_name | female |           avatar            |   city
------------+--------+-----------------------------+----------
 GRAF63     | f      | picture-9411-1299771547.jpg | ALCORCON

I'm trying:

# SELECT g.gid, g.rounds, g.finished,
      p.id, p.money, p.quit,
      i.first_name, i.avatar
 FROM pref_games g
 JOIN pref_scores u USING (gid)
 JOIN pref_scores p USING (gid)
 JOIN pref_users i USING (id)
 WHERE u.id = 'DE9411';

ERROR:  common column name "id" appears more than once in left table

Another try:

# SELECT g.gid, g.rounds, g.finished,
      p.id, p.money, p.quit,
      i.first_name, i.avatar
 FROM pref_games g, pref_users i
 JOIN pref_scores u USING (gid)
 JOIN pref_scores p USING (gid)
 WHERE u.id = 'DE9411' and p.id=i.id;

ERROR:  column "gid" specified in USING clause does not exist in left table

Regards
Alex

--
Sent via pgsql-general mailing list (pgsql-general@postgresql.org) To make
changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-general


------- / Original Message ---------

A) Read the documentation on JOINs until you understand what is going on in
the first query (specifically, how do "ON, NATURAL, USING" relate to each
other and to the JOIN itself)
B) Avoid mixing "JOIN" syntax with multiple tables in the "FROM" clause
C) If you are getting ambiguity in columns you either need to force a JOIN
order (using parentheses) OR revert to using explicit "ON ()" clauses

Note, the "column gid ..." error above result because the planner is trying
to join "pref_users AND pref_scores"  but pref_users does not have a GID
column to join on.  It's as if you wrote:

( (    pref_games    JOIN    (pref_users JOIN pref_scores)   )   JOIN
pref_scores   )

David J.


Re: Saving score of 3 players into a table

От
Alexander Farber
Дата:
The PostgreSQL docs are unfortunately scarce on JOINs
http://www.postgresql.org/docs/8.4/static/tutorial-join.html

I've never seen a JOIN producing several rows instead
of columns before Michael suggested it in this thread

Re: Saving score of 3 players into a table

От
Michael Glaesemann
Дата:
On Oct 27, 2011, at 7:21, Alexander Farber wrote:

> Thank you Michal and others -
>
> On Wed, Oct 26, 2011 at 11:11 PM, Michael Glaesemann
> <grzm@seespotcode.net> wrote:
>> Get games for a particular user:
>>
>> SELECT g.gid, g.rounds, g.finished
>>  FROM pref_games g
>>  JOIN pref_scores u USING (gid)
>>  WHERE u.id = :id;
>>
>> Now, add the participants for those games
>>
>> SELECT g.gid, g.rounds, g.finished,
>>       p.id, p.money, p.quit
>>  FROM pref_games g
>>  JOIN pref_scores u USING (gid)
>>  JOIN pref_scores p USING (gid)
>>  WHERE u.id = :id;
>>
>
> I don't know what kind of JOIN that is (above) - but it works well:

It's just a normal join. There's nothing special about it.

> but now I'm lost even more - how to JOIN this with
> the pref_users table containing first_name, city for each player:
>
> #  select first_name, female, avatar, city
> from pref_users where id = 'DE9411';
> first_name | female |           avatar            |   city
> ------------+--------+-----------------------------+----------
> GRAF63     | f      | picture-9411-1299771547.jpg | ALCORCON
>
> I'm trying:
>
> # SELECT g.gid, g.rounds, g.finished,
>      p.id, p.money, p.quit,
>      i.first_name, i.avatar
> FROM pref_games g
> JOIN pref_scores u USING (gid)
> JOIN pref_scores p USING (gid)
> JOIN pref_users i USING (id)
> WHERE u.id = 'DE9411';
>
> ERROR:  common column name "id" appears more than once in left table

There are two id's: u.id, and p.id. You need to specify which one you're joining on with i:

SELECT g.gid, g.rounds, g.finished,
     p.id, p.money, p.quit,
     i.first_name, i.avatar
  FROM pref_games g
  JOIN pref_scores u USING (gid)
  JOIN pref_scores p USING (gid)
  JOIN pref_users i ON i.id = p.id
  WHERE u.id = 'DE9411';

> Another try:
>
> # SELECT g.gid, g.rounds, g.finished,
>      p.id, p.money, p.quit,
>      i.first_name, i.avatar
> FROM pref_games g, pref_users i
> JOIN pref_scores u USING (gid)
> JOIN pref_scores p USING (gid)
> WHERE u.id = 'DE9411' and p.id=i.id;
>
> ERROR:  column "gid" specified in USING clause does not exist in left table

This is complaining about
  pref_users i
  JOIN pref_scores u USING (gid)

i doesn't have a gid column.

Looks like you could use some work on basic SQL. I recommend picking up a basic SQL book.

Michael Glaesemann
grzm seespotcode net




Re: Saving score of 3 players into a table

От
David Johnston
Дата:
Fair enough.  But look in the SQL Commands section under SELECT (FROM clause) as well, as that gives you the syntax and
meaningand not just an overview of the concept. 

David J.


On Oct 27, 2011, at 8:27, Alexander Farber <alexander.farber@gmail.com> wrote:

> The PostgreSQL docs are unfortunately scarce on JOINs
> http://www.postgresql.org/docs/8.4/static/tutorial-join.html
>
> I've never seen a JOIN producing several rows instead
> of columns before Michael suggested it in this thread
>
> --
> Sent via pgsql-general mailing list (pgsql-general@postgresql.org)
> To make changes to your subscription:
> http://www.postgresql.org/mailpref/pgsql-general