2017-07-31 23 views
0

我有以下查詢:MySQL的左連接(我認爲)難度

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之後我需要使用左連接,但我只是繼續繞圈轉,並且無處可去。

對此的任何指導將不勝感激,非常感謝,艾倫。

+0

你說得對,你需要一個左連接。使用'FROM'語句中的所有表格與使用'INNER JOIN'相同,因此您需要添加表格的'LEFT JOIN'。此外,代碼縮進可以更好地理解SQL。另外,看看這個教程:https://www.sitepoint.com/understanding-sql-joins-mysql-database/ –

+0

你有什麼嘗試?它應該只涉及用'[INNER | LEFT] JOIN'替換FROM中的所有古代逗號,並將相應的連接條件移出WHERE並將ON子句移入適當的連接。 _如果加入的表格被儘可能相鄰排列,這通常也會有所幫助。_ – Uueerdo

+0

代碼縮進是一個簡單但聰明的想法,我會繼續並在遵循兩個建議的同時執行此操作。非常感謝,將會回報。 –

回答

1

首先更換ISNULL:避免隱含JOIN秒。明確說明JOIN,您將更清楚地知道哪個實體與哪個實體相關,並且您永遠不會忘記在您的WHERE中添加AND條件中的一個並獲得笛卡爾產品。

其次:嘗試使用遵循特定邏輯的順序將表放入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到Many,它們是1到(0或1),它們是多對多等。

+1

這感覺就像我試圖去的地方,並且完全有意義。沒有更多的表是可選的。非常感謝,艾倫。 –

1

我是使用JOIN的粉絲,所以我重寫了這樣的查詢。

但請注意,我用戶SQL SERVER/ORACLE而不是MYSQL,所以不知道我的語義是否正確。至少在我的世界裏,使用行不可用的列可能會導致整個結果被過濾掉,所以我使用了函數。

而且通過移動ss.seasonid = 1025到一起,而不是把它留在了那裏,你應該得到的結果,無論那裏現有的SS記錄。

那說,這應該解決您的問題:

編輯 - 與IFNULL

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 
+0

非常感謝您的全面回覆。我得到了以下錯誤「ERROR 1582(42000):調用本地函數'isnull'(我感謝你說你沒有使用MySql)」中的參數計數不正確,但我理解佈局上的思考過程。非常感謝。 –

+0

我的壞...使用** IFNULL ** ...並再次,如果沒有記錄在表** f **,你會遇到問題,這就是爲什麼我包括** IFNULL **功能。另一件事是,imho,** auth_user **似乎是主表,所有其他表都應該遵循它 - 我想! – flaZer