-1

3 つのテーブルを結合しようとしていますが、少し複雑になっています。これは私が持っているものです。チーム名を選択しようとする前は正常に機能していました。また、勝敗をより効果的に計算する方法を誰かが知っていれば、それは役に立ちます.

$sql = '
    SELECT u.name, 
        t.name AS team, 
        SUM(
             CASE WHEN (g.awayScore > g.homeScore AND g.away=u.team) 
                 OR (g.homeScore > g.awayScore AND g.home=u.team) 
             THEN 1 ELSE 0 END
        ) AS wins,
        SUM(
             CASE WHEN (g.awayScore < g.homeScore AND g.away=u.team) 
                 OR (g.homeScore < g.awayScore AND g.home=u.team) 
             THEN 1 ELSE 0 END) AS losses
      FROM game AS g
      JOIN user AS u ON g.away = u.team OR g.home = u.team
      JOIN team AS t ON g.away=t.id OR g.home=t.id
      GROUP BY u.name
    ';  
4

1 に答える 1

1

ではなくに参加teamしたいと思います。テーブルには外部キーである(または) 列があると思います。usergameuserteam_idteamreferences team(id)

クエリに必要な変更は 1 行だけだと思います。これを変更するだけです:

JOIN team AS t ON g.away=t.id OR g.home=t.id

JOIN team AS t ON t.id = u.team

問題を解決するにはこれで十分です。


しかし、クエリの書き方は少し異なります。このようなもの:

SELECT u.name
     , t.name AS team
     , SUM(
         CASE WHEN (g.awayScore > g.homeScore AND g.away=t.id)
                OR (g.homeScore > g.awayScore AND g.home=t.id) 
         THEN 1 ELSE 0 END
       ) AS wins
     , SUM(
         CASE WHEN (g.awayScore < g.homeScore AND g.away=t.id)
                OR (g.homeScore < g.awayScore AND g.home=t.id)
         THEN 1 ELSE 0 END
       ) AS losses
  FROM user u
  JOIN team t ON t.id = u.team
  JOIN game g ON g.away = t.id OR g.home = t.id
 GROUP
    BY u.name
     , t.name

ノート

まず、ユーザー テーブルから始めます。これが、私たちが本当に返したいものです。(どのゲームにも参加していないチームのユーザーにゼロを返したい場合は、OUTER JOIN の実行を検討します。私は常に LEFT JOINS を記述します。)

次に、各ユーザーに関連付けられたチームを取得します。

その後、ゲームに参加します。ここでは少し注意が必要です。ゲームの行を 2 倍にするためです。1 つはアウェイ チームに合わせて、もう 1 つはホーム チームに合わせます。また、チームのユーザーごとに 1 つずつ、行を乗算します。しかし、それらをすべて合計するので、それが必要です。

このようにクエリを記述すると、ユーザーを返すことなく、チームごとにスコアを取得するだけでかなり簡単になります。

SELECT t.name AS team
     , SUM(
         CASE WHEN (g.awayScore > g.homeScore AND g.away=t.id)
                OR (g.homeScore > g.awayScore AND g.home=t.id) 
         THEN 1 ELSE 0 END
       ) AS wins
     , SUM(
         CASE WHEN (g.awayScore < g.homeScore AND g.away=t.id)
                OR (g.homeScore < g.awayScore AND g.home=t.id)
         THEN 1 ELSE 0 END
       ) AS losses
  FROM team t
  JOIN game g ON g.away = t.id OR g.home = t.id
 GROUP
    BY t.name

大規模なセットの場合、それはかなり多数の行になる可能性があり、チームの各ユーザーに対して各チームの行が複製されるため、最初のクエリで多くの行が生成される可能性があります。

したがって、別のアプローチとして、最初にチームのスコアを計算してから、ユーザーに参加することもできます。しかし、それには派生テーブルが必要になります。これは、一時的な MyISAM テーブルを生成し、そこからクエリを実行するためのオーバーヘッドです。(数十人のユーザーがいるトラック チームの場合、これはより効率的かもしれません。しかし、2 人のチーム (ビーチ バレーボール?) の場合は、パフォーマンスが向上しない可能性があります。

上記のチーム スコア クエリを使用すると、それを括弧で囲み、テーブルのように使用できます。team テーブルの id 列も含めたいので、外側のクエリで users テーブルに結合できます。

SELECT u.name
     , s.name AS team
  FROM user u 
  JOIN ( SELECT t.id
              , t.name
              , SUM(
                  CASE WHEN (g.awayScore > g.homeScore AND g.away=t.id)
                         OR (g.homeScore > g.awayScore AND g.home=t.id) 
                       THEN 1 ELSE 0 END
                ) AS wins
              , SUM(
                  CASE WHEN (g.awayScore < g.homeScore AND g.away=t.id)
                         OR (g.homeScore < g.awayScore AND g.home=t.id)
                       THEN 1 ELSE 0 END
                ) AS losses
           FROM team t
           JOIN game g ON g.away = t.id OR g.home = t.id
          GROUP BY t.id, t.name
       ) s
    ON s.id = u.team

インライン ビュー (s のエイリアスが割り当てられます) は、基本的に前の「チーム スコア」クエリと同じです。team.id 列を含めて、外側のクエリでユーザー テーブルに結合できるようにします。

-- 別の代替アプローチ:

SELECT u.name
     , t.name AS team
     , SUM(g.wins) AS wins
     , SUM(g.losses) AS losses
  FROM user u
  JOIN team t ON t.id = u.team
  JOIN ( SELECT gh.home AS team
              , SUM(IF(gh.homeScore > gh.awayScore,1,0)) AS wins
              , SUM(IF(gh.homeScore < gh.awayScore,1,0)) AS losses
           FROM game gh
          GROUP BY gh.home
          UNION ALL
         SELECT ga.away AS team
              , SUM(IF(ga.awayScore > ga.homeScore,1,0)) AS wins
              , SUM(IF(ga.awayScore < ga.homeScore,1,0)) AS losses
           FROM game ga
          GROUP BY ga.away
       ) g
    ON g.team = t.id
 GROUP
    BY u.name
     , t.name

インライン ビュー (上記で g のエイリアスが割り当てられています) は、ホームの勝敗とアウェイの勝敗を別々に計算し、それらを連結しています。home_wins、home_losses、away_wins、および away_losses を個別に返したい場合は、クエリを少し調整できます。そして、これらを外側のクエリに追加して、合計の勝敗を取得できます。

于 2013-08-21T18:55:23.687 に答える