Complex IF statement with 3 tables

馋奶兔 提交于 2019-12-30 11:09:14

问题


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

回答1:


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.




回答2:


You could use a union:

SELECT CASE WHEN winner = participant_id THEN 'Win'
            WHEN winner = opponent_id then 'Loss'
            ELSE method
       END AS result, fighters.name AS opponent, method, event_name, event_date
  FROM fights
  INNER JOIN fighters ON fighter_id = opponent_id
  INNER JOIN events ON event = event_id
  WHERE participant_id = $fighter_id
UNION ALL
SELECT CASE WHEN winner = participant_id THEN 'Loss'
            WHEN winner = opponent_id then 'Win'
            ELSE method
       END AS result, fighters.name AS opponent, method, event_name, event_date
  FROM fights
  INNER JOIN fighters ON fighter_id = participant_id
  INNER JOIN events ON event = event_id
  WHERE opponent_id = $fighter_id
ORDER BY event_date DESC



回答3:


You could just modify you CASE statements to match with $fighter_id.

So your CASE statements would be -

select fight_id,
       CASE
           WHEN winner is not null and winner = f.fighter_id then 'win'
           WHEN winner is not null and winner <> f.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,
        f.name AS participant,
        (SELECT o.name FROM fighters o WHERE o.fighter_id = IF(f.fighter_id = fs.fighter_a, fs.fighter_b, fs.fighter_a)) AS opponent
FROM fights fs,
     fighters f
WHERE f.fighter_id = $fighter_id
AND (fs.fighter_a = f.fighter_id OR fs.fighter_b = f.fighter_id)



回答4:


SELECT
    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 result,
    f2.name opponent,
    method,
    event_name event,
    event_date date
FROM fights f1
INNER JOIN fighters f2
ON f1.fighter_b = f2.fighter_id
INNER JOIN events e
ON e.event_id = f1.event
ORDER BY date DESC


来源:https://stackoverflow.com/questions/11006025/complex-if-statement-with-3-tables

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!