你如何使用左连接而不是分组?

时间:2014-02-25 01:08:42

标签: mysql sql join

我必须采用类似的代码:

SELECT courseId, termId, firstName, lastName
FROM (
   SELECT s.courseId, s.termId, t.teacherId
   FROM Teaches t, Section s
   WHERE s.id = t.sectionId
   GROUP BY s.termId, s.courseId
   HAVING COUNT(DISTINCT t.teacherId) = 1
) Teach, Person p
WHERE p.id = teacherId
ORDER BY courseId, termId;

并将其转换为带有1个子查询的MySql语句,没有任何分组,并且没有仅使用连接的聚合函数(内部联接,左联接等)。我已经尝试了好几个小时,但是我无法找到一种分组的方法而不使用按功能分组。任何见解将不胜感激。

1 个答案:

答案 0 :(得分:3)

我相信这会返回一个等效的结果集,只使用JOIN和一个子查询。 (我没有测试过。)

解决这个难题的一般方法是使用允许的一个子查询,并使用NOT EXISTS谓词来测试是否存在“匹配”行。

 SELECT s.courseId
      , s.termId
      , p.firstName
      , p.lastName
   FROM Section s
   JOIN Teaches t
     ON t.sectionID = s.id
   LEFT
   JOIN Person p
     ON p.id = t.teacherId
  WHERE NOT EXISTS
        ( SELECT 1
            FROM Section c
            JOIN Teaches d
              ON d.sectionId = c.id
           WHERE c.courseId   = s.courseId   -- match (as equivalent to group by)
             AND c.termId     = s.termID     -- match (as equivalent to group by)
             AND c.id        <> s.id         -- but not the same row (count=1)
             AND d.teacherId <> t.teacherId  -- but not the same row (count=1)
        )
  ORDER
     BY s.courseId
      , s.termId

NOT EXISTS谓词中的相关子查询正在寻找匹配的行,但当然,行本身会匹配,因此我们需要将其排除。

我可能不了解哪些列在哪些表中,所以我所拥有的可能不起作用。 (限定查询中的所有列引用都是1)对读者的帮助,可能不知道哪些列在哪些表中,以及2)避免查询无意中被“破坏”与“模糊列”异常,将一个同名的列添加到查询中涉及的其中一个表中。

我已经对Section中的id列和Teaches中的teacherId列的唯一性做了一些假设。

(Section和Teaches的加入使得它更加丑陋,它会更容易看出它是否是一个单独的表。)

SELECT t
  FROM mytable t
 WHERE NOT EXISTS
       ( SELECT 1
           FROM mytable d
          WHERE d.somecol = t.somecol -- a match!
            AND d.id     <> t.id      -- not the same row!
       )

我实际上认为这可以通过反连接模式来解决,而根本不使用任何子查询,但连接在一起的三个表(Section,Teach和Person)使我很难将我的大脑包围起来。