【问题标题】:SQL Server 2005 RIGHT OUTER JOIN not workingSQL Server 2005 RIGHT OUTER JOIN 不起作用
【发布时间】:2011-02-21 21:26:28
【问题描述】:

我正在查找特定课程的访问日志。我需要显示所有课程,即使它们不存在于日志表中。因此外部连接....但是在尝试(大概)LEFT OUTERRIGHT OUTERINNER 的所有变体以及在 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 子句中的某些内容是否阻止我获取 lsn_logs 中不存在的 course_id?这是我加入表格的方式吗?

再次,简而言之,我想要所有 course_id,无论它们是否存在于 lsn_logs 中。

【问题讨论】:

  • 您是否应该考虑从课程到 lsn_logs 进行左连接?
  • 您正在加入lsn_logs 的帐户。如果给定课程没有 log_entry,应该返回什么帐户?
  • @quassnoi - 课程讲师
  • @CheeseConQueso:好的,如果一门课程的日志条目不止一个,l.user_id 不同怎么办?那么应该退回哪个账户呢?
  • @quassnoi - sum/max & group by 加上 ((a.first_name+' '+a.last_name) = c.instructor) 确保只跟踪讲师的聚合

标签: sql sql-server-2005 inner-join outer-join


【解决方案1】:

WHERE 子句中的某些内容是否阻止我获取 lsn_logs 中不存在的 course_id?

是的。

您在 WHERE 子句中使用相等条件,有效地过滤掉由 OUTER JOIN 生成的 NULL 行。

更新:

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

【讨论】:

  • 这就是我的想法......我认为 joe r 和/或 andomars 的答案可能有效,但感谢您的澄清
  • @cheese:你能回答我对你帖子的评论中的问题吗?
【解决方案2】:

要扩展 Quassnoi 的好答案,您可以更改外部连接的工作:

AND l.user_id = a.username

收件人:

AND (l.user_id is null OR l.user_id = a.username)

【讨论】:

  • 帐户和课程表将始终具有匹配的记录,但某些课程和/或帐户的 lsn_logs 将为空
  • @CheeseConQueso:答案已编辑,因此它只检查 lsn_logs 表上的空值
  • 还有这个 - (l.object_id IS NULL OR l.object_id = 'LOGIN')...在答案中提到一些关于空检查的内容
【解决方案3】:

SQL Server 2005 RIGHT OUTER JOIN 确实有效! :)

以下情况如何(我做了一些假设)?:

删除

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 和 accounts 字段添加一些 null 检查,例如:

(l.object_id IS NULL OR l.object_id = 'LOGIN')

【讨论】:

  • 顺便说一句,你有一张非常令人不安的照片! :)
  • 它虽然以一种好的方式令人不安......感谢您的建议,我认为您的双重外部连接可能会起作用
  • 仍然是相同的结果集...不过我知道你在做什么
  • 您还需要进行空检查,例如- (l.object_id 为空或 l.object_id = 'LOGIN')
  • 是的,我没想到,原来是这样
【解决方案4】:

这最终奏效了

Joe R 建议的空检查解决了 Quassnoi 提到的问题

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

【讨论】:

  • 顺便说一句 - 在FROM 部分中可能有更好的方法来完成这一切......请发布任何修改
  • 这会抛出错误“sqlclient data provider error number 8153”,但仍会返回结果....必须调查一下
【解决方案5】:
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...

【讨论】:

  • 不错 - 这和我的一样,但消除了所有的空值检查
  • 您的解决方案返回 1386,而我的解决方案返回 1358...我得调查一下
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-03-10
  • 1970-01-01
  • 2010-10-04
  • 1970-01-01
相关资源
最近更新 更多