2016-10-21 5 views
1

私は、さまざまなソーシャルネットワークからのプレーヤーに関する情報おく削減:は、CTEテーブル内のレコード数のPostgreSQL 9.5.4で

# TABLE words_social; 

    sid | social | female | given | family | photo | place | stamp | uid 
-------+--------+--------+---------+--------+-------+-------+------------+----- 
aaaaa |  1 |  0 | Abcde1 |  |  |  | 1470237061 | 1 
aaaaa |  2 |  0 | Abcde2 |  |  |  | 1477053188 | 1 
aaaaa |  3 |  0 | Abcde3 |  |  |  | 1477053330 | 1 
kkkkk |  3 |  0 | Klmnop3 |  |  |  | 1477053810 | 2 
kkkkk |  4 |  0 | Klmnop4 |  |  |  | 1477053857 | 2 
ggggg |  2 |  0 | Ghijk2 |  |  |  | 1477053456 | 3 
ggggg |  3 |  0 | Ghijk3 |  |  |  | 1477053645 | 3 
ggggg |  4 |  0 | Ghijk4 |  |  |  | 1477053670 | 3 
xxxxx |  4 |  0 | Xyzok |  |  |  | 1470237393 | 4 
(9 rows) 

1、2、3、列social 4つの値は「ツイッターを "フェイスブック" を意味しますその後、カレンを格納し、別のテーブルがある

# select * from words_social s1 WHERE stamp = 
     (SELECT max(stamp) FROM words_social s2 WHERE s1.uid = s2.uid); 

    sid | social | female | given | family | photo | place | stamp | uid 
-------+--------+--------+---------+--------+-------+-------+------------+----- 
aaaaa |  3 |  0 | Abcde3 |  |  |  | 1477053330 | 1 
kkkkk |  4 |  0 | Klmnop4 |  |  |  | 1477053857 | 2 
ggggg |  4 |  0 | Ghijk4 |  |  |  | 1477053670 | 3 
xxxxx |  4 |  0 | Xyzok |  |  |  | 1470237393 | 4 
(4 rows) 

:私は常にによって彼女最新情報を選択することができますプレイヤーのために」など

# select  gid, created, finished, player1, player2 from words_games where player1 = 1 
    union select gid, created, finished, player2, player1 from words_games where player2 = 1; 

gid |   created   | finished | player1 | player2 
-----+-------------------------------+----------+---------+--------- 
    1 | 2016-10-21 14:51:12.624507+02 |   |  4 |  1 
(1 row) 
:( uid 1例)、ユーザがサーバに接続するたびに

# select gid, created, finished, player1, player2 from words_games; 

gid |   created   | finished | player1 | player2 
-----+-------------------------------+----------+---------+--------- 
    1 | 2016-10-21 14:51:12.624507+02 |   |  4 |  1 
    2 | 2016-10-21 14:51:22.631507+02 |   |  3 | 
(2 rows) 

が、私は彼女に彼女がに参加しているゲームを送信:トンのゲームは(私は以下のいくつかの列を省略しています)

私の問題:上記のUNION SELECTステートメントへwords_socialテーブルからユーザー情報を追加する必要があります - 私の2人用ゲームのゲームボードの上にユーザーの写真と名前を表示することができます。

だから私はCTEでこれを試してみてください(とユーザの名でi.given列を追加):

# with user_infos AS (select * from words_social s1 WHERE stamp = 
     (SELECT max(stamp) FROM words_social s2 WHERE s1.uid = s2.uid)) 
select  g.gid, g.created, g.finished, g.player1, g.player2, i.given from words_games g join user_infos i on (g.player1=i.uid) where g.player1 = 1 
union select g.gid, g.created, g.finished, g.player2, g.player1, i.given from words_games g join user_infos i on (g.player2=i.uid) where g.player2 = 1; 

gid |   created   | finished | player1 | player2 | given 
-----+-------------------------------+----------+---------+---------+-------- 
    1 | 2016-10-21 14:51:12.624507+02 |   |  1 |  4 | Abcde3 
(1 row) 

これはうまく動作しますが、私はまだ、次の問題を抱えている -

私は心配していますゲームに多くのプレーヤーがいれば、CTEテーブルuser_infosは非常に大きくなります。

user_infosに関連レコードのみが保持されるようにクエリを書き直すにはどうすればよいですか?私もゲームの対戦相手の(与えられたと家族の名前、写真)に関する情報を必要とするので、私はちょうど

# with user_infos AS (select * from words_social s1 WHERE stamp = 
     (SELECT max(stamp) FROM words_social s2 WHERE s1.uid = s2.uid)) 
     AND s1.uid = 1 
     ... 

を実行することはできません

答えて

1

他の方法でラップする必要があります。

word_gamesから始めて、words_socialテーブルで参加してください。

また、dinstinct on(postgres固有)機能を使用して、2番目のテーブル参照を避けることができます。最終的にはそう

with game_finder as (
select g.gid, g.player1, g.player2 
from words_games g where g.player1 = 1 
union 
select g.gid,g.player2, g.player1 
from words_games g where g.player2 = 1), 
player1_infos as (
select distinct on (uid) 
    gf.gid, 
    uid, 
    social, 
    given 
from words_social ws 
inner join game_finder gf on gf.player1 = ws.uid 
ORDER BY uid, stamp DESC 
), 
player2_infos as (
select gf.gid, 
    uid, 
    social, 
    given 
from words_social ws 
inner join game_finder gf on gf.player2 = ws.uid 
ORDER BY uid, stamp DESC 
) 
select * 
from game_finder gf 
left outer join player1_infos p1 on gf.gid = p1.gid 
left outer join player2_infos p2 on gf.gid = p2.gid; 
+1

だけでなく、あなたも(つまり、DISTINCT ON句よりも高速で、参加LATERALを使用することができますPostgreSQL特有) – Nemeros

+0

ありがとう! 'player2_infos'に' distinct on(uid) 'がありませんか? –

+1

はい、申し訳ありません。同じユーザーの行が重複しています – Nemeros

2

user_infosは、クエリは、次のように書き換えると使用することができます。

with user_infos as (
    select row_number() over (partition by uid order by stamp desc), * from words_social 
) 
select g.gid, g.created, g.finished, g.player1, g.player2, i.given from words_games g 
join user_infos i on g.player1=i.uid and i.row_number = 1 and g.player1 = 1 
union select g.gid, g.created, g.finished, g.player2, g.player1, i.given from words_games g 
join user_infos i on g.player2=i.uid and i.row_number =1 and g.player2 = 1; 
関連する問題