MySQL左连接(我认为)难度

时间:2017-07-31 21:34:28

标签: mysql sql join left-join

我有以下查询:

SELECT 
    u.username as username, 
    s.campaignno as campaign, 
    if(f.hometeamscore>f.awayteamscore,1,0) as Win, 
    if(f.hometeamscore=f.awayteamscore,1,0) as Draw, 
    if(f.hometeamscore<f.awayteamscore,1,0) as Loss, 
    f.hometeamscore as Goals, 
    ss.seasonid as Season, 
    av.avatar as Avatar 
FROM 
    avatar_avatar av, 
    straightred_fixture f, 
    straightred_userselection s, 
    auth_user u, 
    straightred_season ss 
WHERE 
        av.user_id = u.id 
    AND ss.seasonid = 1025 
    AND f.soccerseasonid = ss.seasonid 
    AND s.fixtureid = f.fixtureid 
    AND s.teamselectionid = f.hometeamid 
    AND s.user_id = u.id;

此查询按预期工作,但我现在已经意识到用户可能没有上传个人资料图片。因此,以下部分av.user_id = u.id排除了未上传个人资料照片的任何人。在阅读以下https://www.w3schools.com/sql/sql_join.asp之后,我觉得我需要使用左连接,但我只是继续绕圈而无处可去。

非常感谢任何对此的指导,非常感谢,Alan。

2 个答案:

答案 0 :(得分:1)

我喜欢使用JOIN,所以我重写了这样的查询。

请注意,我使用SQL SERVER / ORACLE而不是MYSQL,因此不确定我的语义是否正确。我使用 IFNULL 函数,因为至少在我的世界中,使用行不可用的列可能导致整个结果被过滤掉。

此外,将 ss.seasonid = 1025 移入联接,而不是将其留在 中,无论是否存在 ss,都应该获得结果记录。

尽管如此,这应该可以解决您的问题:

编辑 - 用IFNULL取代ISNULL

select
 u.username as username
,s.campaignno as campaign
,if(ifnull(f.hometeamscore,0)>ifnull(f.awayteamscore,0),1,0) as Win
,if(ifnull(f.hometeamscore,0)=ifnull(f.awayteamscore,-1),1,0) as Draw
,if(ifnull(f.hometeamscore,0)<ifnull(f.awayteamscore,0),1,0) as Loss
,f.hometeamscore as Goals
,ss.seasonid as Season
,av.avatar as Avatar
from
 auth_user                 u
Left Join 
 avatar_avatar             av on u.id = av.user_id
Left Join
 straightred_userselection s  on u.id =  s.user_id
Left Join
 straightred_fixture       f  on f.hometeamid = s.teamselectionid
                             and f.fixtureid  = s.fixtureid
Left Join
 straightred_season        ss on f.soccerseasonid = ss.seasonid
                             and ss.seasonid = 1025

答案 1 :(得分:1)

首先:避免隐式JOIN。明确JOIN,您将更清楚哪个实体与哪个实体相关,您永远不会忘记在AND中添加WHERE个条件之一并获得笛卡尔产品

第二:尝试使用遵循某个逻辑的顺序将表放在FROM中。在你的情况下,你似乎开始寻找ss.seasonid = 1025 ...(这是WHERE有一个常数的唯一条件)。然后,您的条件列表会产生一定的逻辑顺序...... FROM中的每个表都与前一个表有关系......

那就是说,我认为你需要这个查询:

SELECT 
    u.username as username, 
    s.campaignno as campaign, 
    if(f.hometeamscore>f.awayteamscore,1,0) as Win, 
    if(f.hometeamscore=f.awayteamscore,1,0) as Draw, 
    if(f.hometeamscore<f.awayteamscore,1,0) as Loss, 
    f.hometeamscore as Goals, 
    ss.seasonid as Season, 
    av.avatar as Avatar 
FROM
    straightred_season ss 
    JOIN straightred_fixture f 
        ON f.soccerseasonid = ss.seasonid  
    JOIN straightred_userselection s 
        ON s.fixtureid = f.fixtureid AND s.teamselectionid = f.hometeamid 
    JOIN auth_user u 
        ON u.id = s.user_id
    -- This last table is the one that needs to be LEFT-joined
    -- if the avatar is *optional*. If it isn't there, av.avatar will just
    -- be shown as NULL
    LEFT JOIN avatar_avatar av 
        ON av.user_id = u.id  
WHERE 
    ss.seasonid = 1025 ;

如果更多表的内容是可选,则可能需要多个LEFT JOIN。为了找出有意义的东西,我们需要拥有代表您的场景的完整数据模型或ERD。也就是说,哪些关系是1到1,它们是1到多,它们是1到(0或1),它们是多对多等等。