简体   繁体   English

MySql LeftJoin从三个表

[英]MySql LeftJoin From Three Tables

I am trying to get the data from the game table and whether all gamers have signed up for an available match(Yes/No) An available match is one where the date is current or in the future 我正在尝试从游戏表中获取数据,以及是否所有游戏玩家都已注册了可用的比赛(是/否)。可用的比赛是日期为当前或将来的比赛

Gamers 游戏玩家

(PK)Gamer_Id
Gamer_firstName,
Gamer_lastName,
Gamer experience(Y/N) 

Game_matches 游戏比赛

(PK)FK GamerId,
(PK)FK MatchId,
 Gamer_score

Match 比赛

(PK)Match_Id,
gameDate,
ExperiencedGamers_needed,
InExperiencedGamers_needed

This is what I've tried, I know it's incomplete. 这是我尝试过的,我知道它是不完整的。 Do I need to use a CASE as well? 我还需要使用CASE吗?

SELECT G.*, COUNT(M.`matchId`)
FROM game_matches GM
LEFT JOIN MATCHES M
ON M.`matchId` = GM.`matchId`
LEFT JOIN Gamers G ON G.`userId` = GM.`userId`
WHERE G.`gameDate` >= DATE(NOW())
GROUP BY G.`userId`

Are there any other ways to acheive this other than using the cross join solution from JW? 除了使用JW的交叉联接解决方案之外,还有其他方法可以实现此目的吗?

SELECT  a.GamerID,
        a.Name,
        COUNT(*) = COUNT(c.GamerID)
FROM    Gamers a
        CROSS JOIN `Match` b
        LEFT JOIN GameMatches c
            ON  a.GamerID = c.GamerID AND
                b.MatchID = c.MatchID
WHERE   b.gameDate >= CURDATE()
GROUP   BY  a.GamerID,
            a.Name

What the query does is it first gets the cartesian product of all gamers and all the matches starting today. 该查询的作用是首先获取所有玩家的笛卡尔积和从今天开始的所有比赛。 After that, the results will be joined on table GameMatches on two columns: GamerID and MatchID . 之后,结果将加入到表GameMatches的两列中: GamerIDMatchID

If the result of the cartesian product of the tables has no matches on table GameMatches , the values of the columns are NULL . 如果表的笛卡尔积的结果与表GameMatches不匹配,则列的值为NULL Thus, it test if COUNT(*) which is the total number of records is equal to COUNT(c.GamerID) which is only the total number of gamers that have signed up. 因此,它将测试作为记录总数的COUNT(*)是否等于仅已注册游戏总数的COUNT(c.GamerID)

You are only selecting the games that have matches in the future. 您只选择将来有比赛的游戏。 If you want the count of future matches, you need a conditional aggregation: 如果要计算将来的匹配数,则需要条件聚合:

SELECT G.*, sum(case when g.gameDate >= date(now()) then 1 else 0 end) as FutureMatches
FROM game_matches GM
LEFT JOIN MATCHES M
ON M.`matchId` = GM.`matchId`
LEFT JOIN Gamers G ON G.`userId` = GM.`userId`
GROUP BY G.`userId`

In practice, you may be able to use inner join rather than left join because the ids should match between tables (unless you are interested in users that have no matches at all). 实际上,您可以使用inner join而不是left join因为ID应该在表之间匹配(除非您对完全不匹配的用户感兴趣)。

WITH MATCHES AS
(
SELECT COUNT(*) AS TOTAL_MATCHES FROM MATCH WHERE gameDate >= CURR_DATE
)

GM AS
(SELECT G.GAMER_ID, COUNT(*) AS GAMER_MATCHES
GAMERS G, GAME_MATCHES GM
WHERE G.GAMER_ID = GM.GAMER_ID
GROUP BY G.GAMER_ID
)

SELECT GM.GAMER_ID
FROM GM, MATCH
WHERE GAMER_MATCHES = TOTAL_MATCHES

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM