SQL双外连接?

时间:2011-11-02 21:28:40

标签: sql tsql

我有以下表格:

Users - Users of the site
Matchups - Matchups between two teams
Periods - The periods in which matchups take place
MatchupResults - The results of the matchups
UserPicks - The user's choice of who will win the matchup (5 picks for each period) 
Teams - Teams in the matchups

关系如下:

Matchups.HomeID/Matchups.VisitorID = Teams.ID
Matchups.PeriodID = Periods.ID
MatchupResults.MatchupID = Matchups.ID
UserPicks.MatchupID = Matchups.ID
UserPicks.UserID = User.ID

我想要得到的(英文)是:

所有用户无论他们是否已经取得选秀权和所有比赛,无论他们是否有结果。如果他们有结果或选秀权,我希望他们出现。

我已经得到了这个问题,让我得到了我想要的对决:

select P.ID as PeriodID,
       M.ID as MatchupID,
       V.ID as VisitorTeam,
       H.ID as HomeTeam,
       MR.VisitorScore,
       MR.HomeScore,
       CASE WHEN (M.PointSpread <= 0) THEN
                    CASE WHEN (MR.HomeScore + M.PointSpread > MR.VisitorScore) THEN H.ID ELSE V.ID END
             WHEN (M.PointSpread > 0) THEN
                    CASE WHEN (MR.HomeScore + M.PointSpread < MR.VisitorScore) THEN V.ID ELSE H.ID END
             ELSE NULL
        END AS TeamThatCoveredSpread
from Matchups M
left outer join MatchupResults MR ON MR.MatchupID = M.ID
inner join Teams V ON V.ID = M.VisitorID
inner join Teams H ON H.ID = M.HomeID
inner join Periods P ON P.ID = M.PeriodID

但是我遇到了包括用户和他们的选择在内的问题 - 无论我尝试什么,它都会将我的搜索结果仅过滤到用户选择的游戏。

因此,如果 10个用户并选择 1个匹配,我应该会看到所有10个用户以及 TeamID 作为他们的选择或 NULL 意味着他们没有选择该游戏。

更新:上述查询的示例结果,为简单起见指定了期间1:

enter image description here

4 个答案:

答案 0 :(得分:1)

这里的问题是,您INNER JOIN取决于与LEFT OUTER JOIN的匹配,所以,当然,如果您的LEFT OUTER JOIN没有结果INNER JOIN }无法返回结果。
您需要删除INNER JOIN,因为它们需要MatchupResults

中的数据

让他们每个人LEFT OUTER JOIN,然后将他们的JOIN条件放在WHERE条款中,就像这样......

WHERE 
    (M.[VisitorID] IS NULL OR V.[ID] = M.[VisitorID])
    AND (M.[HomeID] IS NULL OR H.[ID] = M.[HomeID])
    AND (M.[PeriodID] IS NULL OR P.ID = M.[PeriodID])

现在,您的JOIN将继续进行,但仅在MatchupResults JOIN编辑

时有效

答案 1 :(得分:1)

我认为你应该从用户开始,然后LEFT JOIN out。如果你真的想要INNER JOIN,你可以这样做,但你需要把它放在Paranes里面。将JOM CLAUSE中的@Matchupid包含在内也可能是一个好主意,因为这样你就不必担心其他比赛了。

这应该有效(解析但未经过测试)

SELECT 
   P.ID as PeriodID,
   M.ID as MatchupID,
   V.ID as VisitorTeam,
   H.ID as HomeTeam,
   MR.VisitorScore,
   MR.HomeScore,
   CASE WHEN (M.PointSpread <= 0) THEN
                CASE WHEN (MR.HomeScore + M.PointSpread > MR.VisitorScore) THEN H.ID ELSE V.ID END
         WHEN (M.PointSpread > 0) THEN
                CASE WHEN (MR.HomeScore + M.PointSpread < MR.VisitorScore) THEN V.ID ELSE H.ID END
         ELSE NULL
    END AS TeamThatCoveredSpread
FROM   users u 
       LEFT JOIN userpicks up 
         ON u.id = up.user_id 
       LEFT JOIN matchups m 
         ON up.matchupid = m.id 
            AND up.matchupid = @Matchupid 
       LEFT OUTER JOIN (matchupresults mr 
                        INNER JOIN teams v 
                          ON v.id = m.visitorid 
                        INNER JOIN teams h 
                          ON h.id = m.homeid 
                        INNER JOIN periods p 
                          ON p.id = m.periodid) 
         ON mr.matchupid = m.id 

答案 2 :(得分:1)

怎么样:

;WITH matchups (periodid, matchupid, vistortteam,HomeTeam,VisitorScore, HomeScore)
(
SELECT P.ID AS PeriodID
, M.ID AS MatchupID
, V.ID AS VisitorTeam
, H.ID AS HomeTeam
, MR.VisitorScore
, MR.HomeScore
,CASE   WHEN (M.PointSpread <= 0) 
        THEN
                     CASE WHEN (MR.HomeScore + M.PointSpread > MR.VisitorScore) 
                        THEN H.ID 
                     ELSE V.ID END                
        WHEN (M.PointSpread > 0) 
        THEN  
            CASE WHEN (MR.HomeScore + M.PointSpread < MR.VisitorScore) 
                THEN V.ID 
            ELSE H.ID END              
        ELSE NULL         
        END AS TeamThatCoveredSpread 
FROM Matchups M 
LEFT OUTER JOIN MatchupResults MR ON MR.MatchupID = M.ID 
INNER JOIN Teams V ON V.ID = M.VisitorID 
INNER JOIN Teams H ON H.ID = M.HomeID 
INNER JOIN Periods P ON P.ID = M.PeriodID 
)

SELECT *
FROM  USERS u
JOIN USERPIcks up ON u.id = up.userid
LEFT JOIN matchups m  ON m.MatchupID = up.MatchupID

答案 3 :(得分:0)

由于您的建议,我回答了我的问题,并为您的时间标记了您的每个答案和评论。

感谢您宝贵的时间,以下是单个时段/用户的答案和结果集(仅为简单起见而过滤):

insert #UserMatchups
select  U.ID, 
        M.ID, 
        M.VisitorID,
        M.HomeID,
        M.HomeSpread
from Users U, Matchups M
where PeriodID = @PeriodID

select  M.UserID, 
        M.MatchupID,
        CASE WHEN (M.Spread <= 0) THEN
                    CASE WHEN (MR.HomeScore + M.Spread > MR.VisitorScore) THEN M.HomeID ELSE M.VisitorID END
             WHEN (M.Spread > 0) THEN
                    CASE WHEN (MR.HomeScore + M.Spread < MR.VisitorScore) THEN M.VisitorID ELSE M.HomeID END
             ELSE NULL
        END AS TeamThatCoveredSpread,
        UP.TeamID AS UserPick 
from #UserMatchups M
left outer join MatchupResults MR ON MR.MatchupID = M.MatchupID
left outer join UserPicks UP ON UP.UserID = M.UserID and UP.MatchupID = M.MatchupID
where M.UserID = 1

enter image description here