2

順序付けされた MySQL の結果セットでチームのランキングを計算しようとしています。問題は、同点の値で表示される最初のチームの同点を検出することです。

たとえば、結果セットが次のようになっているとします。

team_id    pts
---------------
1          89
2          87
3          76
4          76
5          52

次の PHP でチームのランキングを計算します。

$i = 0;
while($row = mysql_fetch_assoc($r)) { //iterate thru ordered (desc) SQL results
    ++$i;
    ($row['pts'] == $prev_val)
        ? $rnk = 'T-' . $rnk    //same as previous score, indicate tie
        : $rnk = $i;            //not same as previous score
    $rnk = str_replace('T-T-','T-',$rnk); //eliminate duplicative tie indicator
    if ($row['team_id'] == $team_id) { //current team in resultset matches team in question, set team's rank
        $arr_ranks['tp']['cat'] = 'Total Points';
        $arr_ranks['tp']['actual'] = number_format($row['pts'],1);
        $arr_ranks['tp']['league_rank'] = $rnk;
        $arr_ranks['tp']['div_rank'] = $div_rnk;
    }
    else if ($i == 1) { //current team is category leader (rank=1) and is not team in question, set current team as leader
        $arr_ranks['tp']['leader'] = "<a href='index.php?view=franchise&team_id=" . $row['team_id'] . "'>" . get_team_name($row['team_id']) . '</a> (' . number_format($row['pts'],1) . ')';
    }
    $prev_val = $row['pts']; //set current score as previous score for next iteration of loop
}

上記の「同点」ロジックは、チーム #4 をチーム #3 と同点として捉えますが、その逆は捉えません

つまり、チーム #3 の場合$rnk = 3は 、チーム #4 の場合は$rnk = T-3です。(どちらも「T-3」のはずです。)

したがって、問題は次のようになります。結果を繰り返し処理しながら、現在のスコアがリストのさらに下にあるスコアの同点/重複であるかどうかを確認しながら、どのように「先を見て」、後続の重複と一緒に同点として扱うことができますか?

ありがとう。


"wins"編集:以下のように、最初に結果をテーブルに格納すると、Ignacio のコードを実装できます。

select
    s1.team_id,
    t.division_id,
    sum(s1.score>s2.score) tot_wins,
            (   select count(*)
                from wins
                where team_id <> s1.team_id
                and wins > (select wins
                            from wins
                            where team_id = s1.team_id)
            )+1 as rnk
from
    scoreboard s1
    left join teams t
        on s1.team_id = t.team_id
    left join scoreboard s2
        on s1.year=s2.year and s1.week=s2.week and s1.playoffs=s2.playoffs and s1.game_id=s2.game_id and s1.location<>s2.location
group by s1.team_id
order by tot_wins desc;

これにより、次の結果が得られます。

team_id    division_id   tot_wins  rnk
--------------------------------------
10         1             44        1
2          1             42        2
3          2             42        2
8          1             39        4
5          2             37        5
. . .

しかし、私はすでにこの結果セットたどり着いていて、実際には私の問題を解決していません

混乱を避けるために、「フォローアップ」の問題を別に投稿しました。

4

3 に答える 3

2

Ignacio の回答へのリンクが気に入っています。それでも PHP を使用したい場合は、SCORE ごとにランクを収集し、各スコアにチームを割り当てることができます。それはおそらく最も効率的な方法ではありませんが、うまくいくでしょう。

$ranks = array();
while ($row = mysql_fetch_assoc($result)) {
    $ranks[$row['pts']][] = $row['team_id'];
}

$ranks次のような配列になります...

$ranks[89] = array(1);
$ranks[87] = array(2);
$ranks[76] = array(3,4);
$ranks[52] = array(5);

foreachonを使用して$ranks、ポイントがどのように現れるか (昇順または降順) を再確認します。count() を使用して、引き分けかどうかを確認できます。

于 2012-06-01T20:40:39.387 に答える
1
$exists = array();
if ($row['team_id'] == $team_id && !in_array($row['pts'], $exists)) { //current team in resultset matches team in question, set team's rank
        $exists[] = $row['pts'];
        $arr_ranks['tp']['cat'] = 'Total Points';
        $arr_ranks['tp']['actual'] = number_format($row['pts'],1);
        $arr_ranks['tp']['league_rank'] = $rnk;
        $arr_ranks['tp']['div_rank'] = $div_rnk;
    }
于 2012-06-01T18:36:01.973 に答える
1

この質問はここで回答されています。

クエリ:

SELECT a.team_id, a.wins, count(*) instances
FROM
    (SELECT
        s1.team_id,
        sum(s1.score>s2.score) wins
    FROM scoreboard s1
        LEFT JOIN scoreboard s2
            ON s1.year=s2.year
            AND s1.week=s2.week
            AND s1.playoffs=s2.playoffs
            AND s1.game_id=s2.game_id
            AND s1.location<>s2.location
    GROUP BY s1.team_id) AS a
    LEFT JOIN
        (SELECT
            sum(s1.score>s2.score) wins
        FROM scoreboard s1
            LEFT JOIN scoreboard s2
                ON s1.year=s2.year
                AND s1.week=s2.week
                AND s1.playoffs=s2.playoffs
                AND s1.game_id=s2.game_id
                AND s1.location<>s2.location
        GROUP BY s1.team_id) AS b
            ON a.wins = b.wins
GROUP BY a.team_id, b.wins
ORDER BY a.wins DESC;

これにより、出力が得られます...

=================================
|team_id   | wins    |instances |
=================================
|10        | 44      |1         |
|2         | 42      |3         | //tie
|9         | 42      |3         | //tie
|5         | 42      |3         | //tie
|3         | 41      |1         |
|11        | 40      |1         |
|...       |         |          |
=================================

次に、PHP で when をチェックすることで、すべての関係を検出できるようになります$row['instances'] > 1

于 2012-06-13T18:15:16.723 に答える