SQL двойное внешнее соединение? - PullRequest
0 голосов
/ 03 ноября 2011

У меня есть следующие таблицы:

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 matchup, я должен видеть всех 10 пользователей и либо TeamID в качестве их выбора, либо NULL , что означает, что они не сделали выбор для этой игры.

ОБНОВЛЕНИЕ: Пример результатов для вышеуказанного запроса с периодом 1, указанным для простоты:

enter image description here

Ответы [ 4 ]

1 голос
/ 03 ноября 2011

Я думаю, что вы должны начать с пользователей, а затем покинуть их.Если вы действительно хотите ВНУТРЕННЕГО СОЕДИНЕНИЯ, вы можете сделать это, но вам нужно будет поместить его в Паранес.Также, вероятно, будет хорошей идеей включить @Matchupid в JOIN CLAUSE, так как таким образом вам не придется беспокоиться о подборе других совпадений.

Это должно работать (проанализировано, но не проверено)

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 
1 голос
/ 03 ноября 2011

как насчет этого:

;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
1 голос
/ 03 ноября 2011

Проблема здесь в том, что у вас есть INNER JOIN s, которые зависят от совпадения с LEFT OUTER JOIN, поэтому, естественно, если нет результатов из вашего LEFT OUTER JOIN, тогда INNER JOIN не может вернуть результаты.
Вам необходимо исключить ваши INNER JOIN s, поскольку они требуют данных в 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 ed

0 голосов
/ 03 ноября 2011

Я ответил на мою проблему благодаря вашим предложениям и пометил каждый из ваших ответов и комментариев за ваше время.

Спасибо за ваше драгоценное время, вот ответ и набор результатов для одного периода /пользователь (здесь фильтруется только для простоты):

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...