两个表之间的右外连接

Posted

技术标签:

【中文标题】两个表之间的右外连接【英文标题】:right outer join between 2 tables 【发布时间】:2014-04-15 22:07:57 【问题描述】:

我有两张表,一张叫Classes,其中包含ClassName,一张叫FullSchedule,其中包含ClassNameDayValTimeVal等信息。

我想要做的是,我想选择在特定日期和时间没有使用的类,这是我的查询:

    SELECT `Classes`.`ClassName`
    FROM `FullSchedule`
    RIGHT OUTER JOIN `Classes`
    ON `FullSchedule`.`ClassName` = `Classes`.`ClassName`
    WHERE `FullSchedule`.`DayVal` = '$day' AND `FullSchedule`.`TimeVal` = `$time`

虽然我使用RIGHT OUTER JOIN,但结果是使用的类(常见的),即使我将其更改为:

ON `FullSchedule`.`ClassName` != `Classes`.`ClassName`

它向我显示所有类,无论我如何更改它,它要么获取所有类,要么只获取正在使用的类。如何获取未使用的课程?

【问题讨论】:

请注意,实际上没有人使用 RIGHT JOIN。没有错 - 这对许多人(包括我)来说只是有点违反直觉 - 但也许这是西方的,从左到右的写作方式。 【参考方案1】:

试试这个:

SELECT `Classes`.`ClassName`
    FROM `Classes`
WHERE Classes`.`ClassName` not in ( 
SELECT `FullSchedule`.`ClassName`
FROM `FullSchedule`
WHERE `FullSchedule`.`DayVal` = '$day' AND `FullSchedule`.`TimeVal` = `$time` )

【讨论】:

我都试过了,但还是不行,它给了我所有的课程:/ 您确定在 FullSchedule 和 Classes 表中有同名的类吗? SELECT Classes.ClassName FROM Classes WHERE Classes.ClassName` not in ( SELECT FullSchedule.ClassName FROM FullSchedule)所有课程? 它返回零行! 那么变量 $day 和 $time 的问题。查询没问题。【参考方案2】:

首先从表FullSchedule中检索具有WHERE条件的数据,然后RIGHT JOIN它到Classes

SELECT 
    c.`ClassName`
FROM (
    SELECT 
      `ClassName`
    FROM
      `FullSchedule`
    WHERE
      `DayVal` = '$day' AND `TimeVal` = '$time'
) f RIGHT OUTER JOIN `Classes` c
ON f.`ClassName` != c.`ClassName`

【讨论】:

@Ibraheem Ismail : echo 您的查询,复制输出并在您的 sql 管理工具(如 phpmyadmin)中执行它。如果它返回零行,那么问题出在您的数据库中,否则,如果它返回错误,您将绝对确定建议的查询不正确。【参考方案3】:

JOIN 选项的替代方案:

SELECT c.ClassName
FROM   Classes c
WHERE NOT EXISTS ( SELECT * 
                   FROM   FullSchedule fs 
                   WHERE fs.DayVal = $day
                     AND fs.TimeVal = $time
                     AND fs.ClassName = c.ClassName )

我建议您将所有三种解决方案都放入您的分析器中,并比较执行计划以找出最适合您的环境的方案。

如果RIGHT OUTER JOIN 语法是绝对必要的:

SELECT c.ClassName
FROM   FullSchedule fs
         RIGHT OUTER JOIN Classes c
         ON  fs.ClassName = c.ClassName
         AND fs.DayVal = $day
         AND fs.TimeVal = $time
WHERE  fs.ClassName IS NULL

RIGHT OUTER JOIN 确保Classes 表返回其所有行,然后匹配ClassName 上的FullSchedule 行以及DayValTimeVal 值分别等于$day$time 的行.

WHERE 子句消除了FullSchedule 表(具有ClassNameDayValTimeVal 限制)没有匹配记录的行。

【讨论】:

【参考方案4】:
 SELECT c.ClassName
   FROM classes c
   LEFT 
   JOIN FullSchedule s
     ON s.ClassName = c.ClassName
    AND s.DayVal = '$day' 
    AND s.TimeVal = '$time' -- <-- NOT BACKTICKS
  WHERE s.ClassName IS NULL;

考虑将日期和时间存储为单个实体。好得多的主意。

【讨论】:

以上是关于两个表之间的右外连接的主要内容,如果未能解决你的问题,请参考以下文章

左外连接与右外连接区别?

Oracle 右外连接

右外连接问题

左外连接和右外连接的区别

SQL:内连接左外连接右外连接全连接交叉连接区别

右外连接和内连接使用三个select语句