[pgsql-jp: 37428] Re: 一部のデータを SELECT した際に全体の順位取得

TANAKA Masayuki tanakamasayuki @ gmail.com
2006年 8月 18日 (金) 17:22:40 JST


こんにちは田中です

> 私がPHP初級レベルゆえ、示して下さったPHPをちゃんと理解出
> 来ていないので、間違えだったら申し訳ないのですが、
> この方法だと、同点の場合ランキングが同一にはならなくない
> でしょうか。
> また、次ページ等推移した際に例えば6〜10位も表示はされる
> のでしょうか。

サンプルで投げたのは内容自体はあまり意味はありませんでした
利用方法一例です

同率順位がいる場合には

1、集計用のテンポラリテーブルを作る(複数ランキングの合算)
2、一番上に表示されるユーザーの順位を取得する
3、PHP上で順位をつけていく

って感じでしょうか
順位取得が重くなる場合にはこんな感じにしています

PHP上ではトップの順位がわかっていますので、同じ得点の
場合にはカウントアップせず、違う点になったら次の点まで
飛ぶます

一発で計算できたほうがいいですが、SQLによっては一気に
重くなりますので、分割するのも手だと思います

同率がない場合には offset とループ数で順位を出せますので
SQLで計算する必要はないと思います

重い場合には、1の合算部分は成績がアップされたときに
自分の分だけ更新するようにしていたほうが安全です

#個人的には絶対に同率にならない条件をつけたほうが楽だと思います

田中

> > こんばんは田中です
> >
> > 私はPHP上で配列に追加しちゃいます
> >
> > $list = array();
> > while( $row = $res->fetchRow( DB_FETCHMODE_ASSOC ) )
> > {
> >       $row['start_times1'] = time_str( $row['start_time1'] );
> >       $row['start_times2'] = time_str( $row['start_time2'] );
> >       $row['start_times3'] = time_str( $row['start_time3'] );
> >       $row['end_times1'] = time_str( $row['end_time1'] );
> >       $row['end_times2'] = time_str( $row['end_time2'] );
> >       $row['end_times3'] = time_str( $row['end_time3'] );
> >       $row['recesss'] = time_str( $row['recess'] );
> >       $row['workings'] = time_str( $row['working'] );
> >       $list[] = $row;
> > }
> > $smarty->assign( 'list', $list );
> >
> > SQLでやるよりは単純で早いはず。。。
> >
> > 田中
> >
> > 06/08/17 に whi te<white_wwjd @ yahoo.co.jp> さんは書き
> ました:
> > > ご返信ありがとうございます。
> > >
> > > > 順位 =(自分より大きい points の人の数+1)と考
> える
> > > と、
> > >
> > > なるほど。
> > > 確かに順位ってそういう事ですね。
> > > 順位の意味(!?)を考えてみた事なかったですが、
> > > そういう風に考え直すと、SQL文が作成出来ますね。
> > > 勉強になりました。
> > >
> > > ただ、実際のデータってランキングテーブルに
> > > 同一人物のデータが複数存在します。
> > > ですので、例示して頂いたSQLを基に以下の様なSQL文を作
> 成し
> > > てみたのですが、エラーが出てしまいます。
> > >
> > > COUNT/SUMしたデータを条件文に含む事は出来ないのでし
> ょう
> > > か。
> > > ON句のSUMを試しに抜かしてみると、結果は違いますが、
> > > SQLはとおります。
> > >
> > > SELECT r1.name,r1.points,SUM(r2.points)+1 as rank
> > > FROM ランキング r1 LEFT JOIN ランキング r2 ON
> > > SUM(r1.points) < SUM(r2.points)
> > > GROUP BY r1.name,r1.points,r2.points
> > > ORDER BY rank DESC
> > >
> > > ERROR:  aggregates not allowed in JOIN conditions
> > >
> > >
> > >
> > >
> > >
> > > > 賀内と申します。
> > > >
> > > > > TABLE名:ランキング
> > > > >
> > > > > name|points
> > > > > -----------
> > > > > aa  |60
> > > > > bb  |80
> > > > > cc  |70
> > > > > dd  |40
> > > > > ee  |20
> > > > >
> > > > >
> > > > > SELECT * FROM ランキング OFFSET 2 LIMIT 2 ORDER BY
> > > points
> > > > > DESC;
> > > > >
> > > > > name|points
> > > > > aa  |60
> > > > > dd  |40
> > > > >
> > > > > が取得されると思いますが、「aa」が全体の何位かを
> 取得
> > > する
> > > > > 事は出来ないでしょうか。
> > > > > 以下の様に取得するのが理想です。
> > > > >
> > > > > name|points|rank
> > > > > aa  |60    |3
> > > > > dd  |40    |4
> > > >
> > > > 順位 =(自分より大きい points の人の数+1)と考
> える
> > > と、
> > > >
> > > >  SELECT r1.name,r1.points,count(r2.*)+1 as rank
> > > >  FROM ランキング r1 LEFT JOIN ランキング r2 ON
> r1.points
> > > < r2.points
> > > >  GROUP BY r1.name,r1.points
> > > >  ORDER BY rank
> > > >
> > > > と書けますよ。
> > > > これだと OFFSET / LIMIT も使えるし、同じ points の
> 人が
> > > いても大丈夫です。
> > > >
> > >
>



pgsql-jp メーリングリストの案内