Search code examples
mysqlrelational-databaserelational

Complex IF statement with 3 tables


This is a continuation of this question from yesterday.

Here are my three tables:

Fighters Table

fighter_id |  name
-----------------------
1          | John
2          | Steve
3          | Bill
4          | Bobby

Events Table

event_id  |  event_name  |  event_date
-------------------------------------------
1          | MMA         |  01/01/2010
2          | Cool        |  02/20/2010
3          | Yeaa!       |  04/15/2010

Fights Table

fight_id  |  fighter_a  |  fighter_b  |  winner  |  method  |  event
-----------------------------------------------------------------------
1         | 1           |  2          |  1       | Sub      | 1
2         | 4           |  1          |  4       | KO       | 2
3         | 1           |  3          |  NULL    | Draw     | 3

Result trying to get

result  |  opponent  |  method  |  event  |  date        
----------------------------------------------------------
Draw    | Bill       |  Draw    |  Yeaa!  |  04/15/2010  
Loss    | Bobby      |  KO      |  Cool   |  02/20/2010 
Win     | Steve      |  Sub     |  MMA    |  01/01/2010

So in the fights table, fighter_a, fighter_b, and winner are integers that correspond to fighter_id in the Fighters table.

I'm basically on a page retrieving data based on fighter_id ($fighter_id).

I'm trying to create rows with each fight of that fighter that includes his opponent's name, result (win, loss, draw, or nc), method, event_name, and event_date. The challenge is that a winner can be in either fighter_a or fighter_b. It's not always in the same column. I appreciate any help I can get.

select 
    fight_id,
    CASE
      WHEN winner is not null and winner=fighter_id then 'win'
      WHEN winner is not null and winner<>fighter_id then 'loss'
      WHEN winner is null and method='Draw' then 'draw'
      WHEN winner is null and method = 'No Contest' then 'no contest'
      ELSE ''
    END as match_result,
    participant.name 'participant',
    opponent.name 'opponent'
FROM fights
    INNER JOIN fighters as participant on participant.fighter_id = fights.fighter_a
    INNER JOIN fighters as oppoent on opponent.fighter_id = fights.fighter_b
WHERE 
    fighter_a=$fighter_id OR fighter_b=$fighter_id
ORDER BY
    event_date DESC

Solution

  • Use a subselect with conditionals to switch the fighter_id you're looking for to column_a if it's in column_b, that way, it simplifies your operations and joins in the outer query:

    SELECT
        (
            CASE
                WHEN a.winner = a.f_a THEN 'Win'
                WHEN a.winner = a.f_b THEN 'Loss'
                WHEN a.winner IS NULL THEN a.method
            END
        ) AS result,
        b.name AS opponent,
        a.method AS method,
        c.event_name AS event,
        c.event_date AS date
    FROM
        (
            SELECT 
                IF(fighter_b = $fighter_id, fighter_b, fighter_a) AS f_a,
                IF(fighter_b = $fighter_id, fighter_a, fighter_b) AS f_b,
                winner,
                method,
                event
            FROM 
                fights
            WHERE
                $fighter_id IN (fighter_a, fighter_b)
        ) a
    INNER JOIN
        fighters b ON a.f_b = b.fighter_id
    INNER JOIN
        events c ON a.event = c.event_id
    ORDER BY
        c.event_date DESC
    

    Also, if the winner field is null, then just echo the method field. That way, when you want to add yet another type of method where winner is null to your system, you don't have to keep tacking on more conditional checks to your CASE statement.