SQL Server 2005 RIGHT OUTER JOIN не работает - PullRequest
7 голосов
/ 20 мая 2010

Я просматриваю журналы доступа для конкретных курсов. Мне нужно показать все курсы, даже если они не существуют в таблице журналов. Отсюда и внешнее соединение .... но после попытки (предположительно) всех вариантов LEFT OUTER, RIGHT OUTER, INNER и размещения таблиц в коде SQL я не смог получить свой результат. *

Вот что я бегу:

SELECT   (a.first_name+' '+a.last_name) instructor,
            c.course_id,
            COUNT(l.access_date) course_logins,
            a.logins system_logins,
            MAX(l.access_date) last_course_login,
            a.last_login last_system_login
FROM       lsn_logs l RIGHT OUTER JOIN courses c ON l.course_id = c.course_id,
            accounts a
WHERE     l.object_id = 'LOGIN' 
            AND c.course_type = 'COURSE' 
            AND c.course_id NOT LIKE '%TEST%' 
            AND a.account_rights > 2
            AND l.user_id = a.username
            AND ((a.first_name+' '+a.last_name) = c.instructor)
GROUP BY    c.course_id, 
            a.first_name, 
            a.last_name,
            a.last_login,
            a.logins,
            c.instructor
ORDER BY    a.last_name,
            a.first_name,
            c.course_id,
            course_logins DESC

Что-то в предложении WHERE мешает мне получить course_id, которых нет в lsn_logs? Это способ, которым я присоединяюсь к столам?

Опять же, короче говоря, я хочу, чтобы все course_id независимо от их существования в lsn_logs.

Ответы [ 5 ]

8 голосов
/ 20 мая 2010

Что-то в предложении WHERE мешает мне получить course_id, которых нет в lsn_logs?

Да, это так.

Вы используете условия равенства в предложении WHERE, которые эффективно отфильтровывают строки NULL, сгенерированные OUTER JOIN.

Обновление:

SELECT  c.instructor,
        c.course_id,
        l.course_logins,
        a.logins system_logins,
        l.last_course_login,
        a.last_login last_system_login
FROM    courses с
JOIN    accounts a
ON      a.first_name + ' ' + a.last_name = c.instructor
CROSS APPLY
        (
        SELECT  COALESCE(COUNT(access_date), 0) course_logins,
                MAX(access_date) last_course_login
        FROM    lsn_logs l
        WHERE   l.object_id = 'LOGIN'
                AND l.course_id = c.course_id
                AND l.user_id = a.username
        ) l
WHERE   c.course_type = 'COURSE' 
        AND c.course_id NOT LIKE '%TEST%' 
        AND a.account_rights > 2
ORDER BY
        a.last_name,
        a.first_name,
        c.course_id,
        course_logins DESC
2 голосов
/ 20 мая 2010
SELECT...    
FROM courses c
     INNER JOIN accounts a
        ON (a.first_name+' '+a.last_name) = c.instructor
     LEFT OUTER JOIN lsn_logs l
        ON l.course_id = c.course_id
        AND l.user_id = a.username
        AND l.object_id = 'LOGIN' 
WHERE c.course_type = 'COURSE'  
    AND c.course_id NOT LIKE '%TEST%'
    AND a.account_rights > 2 
    AND a.logins > 0 
GROUP BY...
ORDER BY...
2 голосов
/ 20 мая 2010

Чтобы расширить хороший ответ Quassnoi, чтобы сработало внешнее объединение:

AND l.user_id = a.username

Кому:

AND (l.user_id is null OR l.user_id = a.username)
1 голос
/ 20 мая 2010

Правильное соединение с SQL Server 2005, безусловно, работает! :)

Как насчет следующего (я сделал некоторые предположения)?:

удалить

AND l.user_id = a.username 

и измените соединения на

dbo.courses c
LEFT OUTER JOIN lsn_logs l
ON c.course_id = l.course_id
LEFT OUTER JOIN accounts a
ON l.user_id = a.username 

и добавьте несколько нулевых проверок для полей lsn_logs и account, например:

(l.object_id IS NULL OR l.object_id = 'LOGIN')
0 голосов
/ 20 мая 2010

Это сработало

Нулевые проверки, предложенные Джо Р., решили проблему, о которой упоминал Кассной

SELECT   (a.first_name+' '+a.last_name) instructor,
            c.course_id,
            COUNT(l.access_date) course_logins,
            a.logins system_logins,
            MAX(l.access_date) last_course_login,
            a.last_login last_system_login
FROM       lsn_logs l RIGHT OUTER JOIN courses c ON l.course_id = c.course_id,
            accounts a
WHERE     (l.object_id IS NULL OR l.object_id = 'LOGIN') 
            AND c.course_type = 'COURSE' 
            AND c.course_id NOT LIKE '%TEST%' 
            AND a.account_rights > 2
            AND (l.user_id = a.username OR l.user_id IS NULL)
            AND ((a.first_name+' '+a.last_name) = c.instructor)
            AND a.logins > 0
GROUP BY    c.course_id, 
            a.first_name, 
            a.last_name,
            a.last_login,
            a.logins,
            c.instructor
ORDER BY    a.last_name,
            a.first_name,
            c.course_id,
            course_logins DESC
...