【问题标题】:perform true on joined tables在连接表上执行 true
【发布时间】:2013-05-04 10:31:38
【问题描述】:

在 PostgreSQL 8.4.13 中,我有两个表格代表纸牌游戏(每个有 3 名玩家)和这些游戏的得分结果。玩家由id 列标识,游戏由gid 标识:

# \d pref_games
                                    Table "public.pref_games"
 Column |            Type             |                        Modifiers
--------+-----------------------------+----------------------------------------------------------
 gid    | integer                     | not null default nextval('pref_games_gid_seq'::regclass)
 rounds | integer                     | not null
 stamp  | timestamp without time zone | default now()
Indexes:
    "pref_games_pkey" PRIMARY KEY, btree (gid)
Referenced by:
    TABLE "pref_scores" CONSTRAINT "pref_scores_gid_fkey" FOREIGN KEY (gid) REFERENCES pref_games(gid) ON DELETE CASCADE

# \d pref_scores
         Table "public.pref_scores"
 Column  |         Type          | Modifiers
---------+-----------------------+-----------
 id      | character varying(32) | not null
 gid     | integer               | not null
 money   | integer               | not null
 last_ip | inet                  |
 quit    | boolean               |
Indexes:
    "pref_scores_pkey" PRIMARY KEY, btree (id, gid)
    "pref_scores_gid_index" btree (gid)
Foreign-key constraints:
    "pref_scores_gid_fkey" FOREIGN KEY (gid) REFERENCES pref_games(gid) ON DELETE CASCADE
    "pref_scores_id_fkey" FOREIGN KEY (id) REFERENCES pref_users(id) ON DELETE CASCADE

我正在尝试找出拥有id='OK261593357402' 的玩家是否曾与玩家id='MR3689735717800138910' 一起玩过 - 以便我可以让他们在我的网站上互相评分。

我想我需要在inner join 上拨打perform true - 请问这是正确的吗?

所以我正在尝试:

# select * from pref_games g inner join pref_scores s on (s.gid=g.gid) where s.id='OK261593357402';
   gid   | rounds |           stamp            |       id       |   gid   | money |    last_ip     | quit
---------+--------+----------------------------+----------------+---------+-------+----------------+------
 2124241 |     20 | 2013-05-01 12:26:54.052086 | OK261593357402 | 2124241 |    28 | 93.232.91.105  | f
 2125575 |     17 | 2013-05-01 16:53:21.090822 | OK261593357402 | 2125575 |    32 | 93.232.91.105  | f
 2125881 |     20 | 2013-05-01 17:47:26.15633  | OK261593357402 | 2125881 |   -31 | 93.232.91.105  | f
 2126242 |      0 | 2013-05-01 18:41:06.769132 | OK261593357402 | 2126242 |     0 | 93.232.91.105  | f
 2126244 |      0 | 2013-05-01 18:41:12.495192 | OK261593357402 | 2126244 |     0 | 93.232.91.105  | t
 2126259 |      0 | 2013-05-01 18:42:39.974518 | OK261593357402 | 2126259 |     0 | 93.232.91.105  | t
 2126613 |     33 | 2013-05-01 19:27:11.88462  | OK261593357402 | 2126613 |  -132 | 93.232.91.105  | f
 2126813 |      0 | 2013-05-01 19:57:05.23061  | OK261593357402 | 2126813 |     0 | 93.232.91.105  | t
 2127299 |     20 | 2013-05-01 20:36:42.021133 | OK261593357402 | 2127299 |   136 | 93.232.91.105  | f
 2127821 |      0 | 2013-05-01 21:33:32.168757 | OK261593357402 | 2127821 |     0 | 93.232.91.105  | f
 2127830 |      0 | 2013-05-01 21:34:47.694645 | OK261593357402 | 2127830 |     0 | 93.232.91.105  | t
 2128012 |     21 | 2013-05-01 22:04:03.850061 | OK261593357402 | 2128012 |    55 | 93.232.91.105  | f
 2129551 |     13 | 2013-05-02 10:08:37.348426 | OK261593357402 | 2129551 |   -32 | 79.250.39.175  | f
 2129818 |     13 | 2013-05-02 11:21:50.998484 | OK261593357402 | 2129818 |    71 | 79.250.39.175  | f
 2130467 |     11 | 2013-05-02 13:55:00.034698 | OK261593357402 | 2130467 |   -79 | 79.250.39.175  | f
 2130470 |      0 | 2013-05-02 13:55:41.298932 | OK261593357402 | 2130470 |     0 | 79.250.39.175  | f
 2130476 |      0 | 2013-05-02 13:56:22.359713 | OK261593357402 | 2130476 |     0 | 79.250.39.175  | f
.....

但我只看到上面的id='OK261593357402',即我期待看到他所有的游戏伙伴,但他们没有交付。

我也试过了:

# select * from pref_games g left outer join pref_scores s on (s.gid=g.gid) where s.id='OK261593357402';
   gid   | rounds |           stamp            |       id       |   gid   | money |    last_ip     | quit
---------+--------+----------------------------+----------------+---------+-------+----------------+------
 2124241 |     20 | 2013-05-01 12:26:54.052086 | OK261593357402 | 2124241 |    28 | 93.232.91.105  | f
 2125575 |     17 | 2013-05-01 16:53:21.090822 | OK261593357402 | 2125575 |    32 | 93.232.91.105  | f
 2125881 |     20 | 2013-05-01 17:47:26.15633  | OK261593357402 | 2125881 |   -31 | 93.232.91.105  | f
 2126242 |      0 | 2013-05-01 18:41:06.769132 | OK261593357402 | 2126242 |     0 | 93.232.91.105  | f
 2126244 |      0 | 2013-05-01 18:41:12.495192 | OK261593357402 | 2126244 |     0 | 93.232.91.105  | t
 2126259 |      0 | 2013-05-01 18:42:39.974518 | OK261593357402 | 2126259 |     0 | 93.232.91.105  | t
 2126613 |     33 | 2013-05-01 19:27:11.88462  | OK261593357402 | 2126613 |  -132 | 93.232.91.105  | f
 2126813 |      0 | 2013-05-01 19:57:05.23061  | OK261593357402 | 2126813 |     0 | 93.232.91.105  | t
...

不幸的是,同样的结果......

我是否应该只制作一系列 selects 和 exists in 来代替?

【问题讨论】:

  • perform true 是什么?某种 Oracle 主义或专有 PostgreSQL 扩展的特性?
  • 我的意思是:PERFORM TRUE FROM ....,然后是IF FOUND THEN .... ENDIF
  • 哦,您说的是 PL/PgSQL 的 PERFORMSELECT 的无结果返回替代方案,然后测试 FOUND。好吧,这有点道理。你从来没有说过任何关于 PL/PgSQL 或者你正在编写存储函数的事情。 (这是在问题中显示代码的一个好主意)。

标签: postgresql join plpgsql exists postgresql-8.4


【解决方案1】:

我正在尝试找出拥有id='OK261593357402' 的玩家是否拥有 曾经和玩家一起玩过id='MR3689735717800138910'

plpgsql 中使用 IF EXISTS ... 通常比带有尾随 IF FOUND ...PERFORM 更短/更快/更简单/更优雅:

IF EXISTS (
   SELECT 1
   FROM   pref_scores p1
   JOIN   pref_scores p2 USING (gid)
   WHERE  p1.id = 'OK261593357402'
   AND    p2.id = 'MR3689735717800138910'
   ) THEN
   -- do stuff
END IF;

您根本不需要pref_games 来回答您的问题。

【讨论】:

  • 谢谢!你说得对,不需要pref_games 表,非常有见地:-)
【解决方案2】:
select pg.*, ps.id, ps2.id
from
    pref_games pg
    inner join
    pref_scores ps on pg.gid = ps.gid
    inner join
    pref_scores ps2 on ps.gid = ps2.gid
where
    ps.id = 'OK261593357402'
    and ps2.id != 'OK261593357402'

【讨论】:

    猜你喜欢
    • 2018-12-22
    • 2022-08-23
    • 2012-07-17
    • 1970-01-01
    • 1970-01-01
    • 2020-10-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多