2016-07-13 51 views
1

我有以下SQL查询:从连接表仅当记录存在

SELECT 
Customers.CustomerName AS FullName, 
Customers.Id AS CustomerId, 
Customers.UserRoleId AS UserRoleId, 
Customers.Email AS Email, 
IFNULL(Customers.StudentId, '') AS CustomersStudentId, 
IFNULL(Customers.MagentoId, '') AS MagentoId, 

Sections.Id AS SectionId, 
Sections.SectionNumber AS SectionNumber, 
Sections.SectionName AS SectionName, 

Courses.Id AS CourseId, 
IFNULL(Courses.CourseName, '') AS CourseName, 
IFNULL(Courses.CourseNumber,'') AS CourseNumber, 
IFNULL(Courses.CourseDepartment, '') AS CourseDepartment, 
IFNULL(Courses.Notes, '') AS CourseNotes, 
IFNULL(Courses.Year, '') AS CourseYear, 
IFNULL(Courses.CourseType, '') AS CourseType, 

StudentsCourses.Id AS StudentsCoursesId, 
IFNULL(StudentsCourses.StudentId, '') AS StudentsCoursesStudentId, 

IFNULL(SiteProfile.StudentIdField, '') AS StudentIdField, 
IFNULL(SiteProfile.SchoolEmailDomain, '') AS SchoolEmailDomain, 

IFNULL(Orders.Id, '') AS OrderId 

FROM Customers 
    LEFT JOIN StudentsCourses ON Customers.Id = StudentsCourses.CustomerId 
    LEFT JOIN Sections ON StudentsCourses.SectionId = Sections.Id 
    LEFT JOIN Courses ON StudentsCourses.CourseId = Courses.Id 
    LEFT JOIN BooksCourses ON Courses.Id = BooksCourses.CourseId 
    LEFT JOIN Products ON BooksCourses.ISBN = Products.ISBN 
    LEFT JOIN EbookVendors ON Products.EbookVendorId = EbookVendors.Id 
    LEFT JOIN Orders ON Customers.Id = Orders.CustomerId 
    LEFT JOIN SiteProfile ON Courses.SchoolCode = SiteProfile.SchoolCode 

WHERE Customers.Id <> 10 
    AND StudentsCourses.SectionId IS NOT NULL 
    AND StudentsCourses.Delete <> 2 
    AND Courses.SchoolCode = '{$criteria["school_code"]}' 
    AND Courses.Year = {$criteria["year"]} 
    AND Courses.CourseType LIKE '{$criteria["term"]}' 

记录会一直存在于Customers表。但是有时在任何其他连接的表中都不会有关联的记录。

如何修改查询,以便在Customers表中只有记录时,附加的SELECTWHERE子句不会中断结果?

编辑:

当记录只在Customers存在,我希望这个纪录,我想WHERE条款,不属于该Customers表被忽略。

如果记录存在于连接表中,我希望与该连接表有关的WHERE子句起作用。

+0

解释得更好...请....只需要客户和其他人表之间匹配的结果,或者您希望两者都有....别名匹配结果和客户与其他表之间不匹配的结果? – scaisEdge

+0

更加清晰地编辑 – LXXIII

+1

将不在客户表中的记录上的连接限制批评移至连接。例如:'LEFT JOIN StudentsCourses ON Customers.Id = StudentsCourses.CustomerId and StudentsCourses.SectionId IS NOT NULL AND St​​udentsCourses.Delete <> 2'限制应用于连接之前,因此在与studentsCourses的连接为空时保留客户记录。在使用外部连接时,大部分时间都需要在连接之前执行。或者你必须像其他人在下面的答案中所做的那样解决空值问题。 – xQbert

回答

1

您需要更改where语句来处理空值。像这样

WHERE Customers.Id <> 10 
    -- AND StudentsCourses.SectionId IS NOT NULL 
    AND COALESCE(StudentsCourses.Delete,0) <> 2 
    AND COALESCE(Courses.SchoolCode,'{$criteria["school_code"]}') = '{$criteria["school_code"]}' 
    AND COALESCE(Courses.Year,{$criteria["year"]}) = {$criteria["year"]} 
    AND (Courses.CourseType is null or Courses.CourseType LIKE '{$criteria["term"]}') 

当你离开加盟和值不存在,你将有空这些项目 - 仍然看你需要没有你的where语句筛选出这些项目的行。

还有另一种方法可以将标准放入连接中。因此,例如课程类型应该是这样的:

LEFT JOIN Courses ON StudentsCourses.CourseId = Courses.Id and Courses.CourseType LIKE '{$criteria["term"]}' 

如果你这样做,那么你就不需要过滤器添加到哪里 - 这将只适用于加入,将返回null了表列如果联接不存在。

+0

太棒了。这两个答案都向我展示了SQL可能带来的新东西。我会尝试他们,并回来! – LXXIII

+0

@LXXIII - 很好!祝你好运。 – Hogan

1

当你离开加盟,你会得到在其中有没有相应的“正确”的记录中的字段NULL值,所以你要考虑的是:

WHERE Customers.Id <> 10 
    -- AND StudentsCourses.SectionId IS NOT NULL 
    AND (StudentsCourses.Delete <> 2 OR StudentsCourses.Delete IS NULL) 
    AND (Courses.SchoolCode = '{$criteria["school_code"]}' OR Courses.SchoolCode IS NULL) 
    AND (Courses.Year = {$criteria["year"]} OR Courses.Year IS NULL) 
    AND (Courses.CourseType LIKE '{$criteria["term"]}' OR Courses.CourseType IS NULL) 
+0

如果'StudentsCourses.Delete'为'null',则记录可能存在,但Delete标志未被设置。我希望在那种情况下显示该记录。 – LXXIII

+1

@LXXII - 就像在我的例子中,这将显示该记录。 – Hogan

1

都错了。你不能有一个返回两个不同形式的元组的查询:如果存在这些列,那么这些列将存在,但是如果存在这些列的话,那么这些列就存在。一个查询,一个形状。

我们已经严厉地说过,让我们放松一下。

只要做一个外部连接,并且如果要连接的数据不存在(=找不到),NULL值将会静静地,无痛地填充到指定的列中。 “填充”是一个更有趣的词。

+0

我认为你是对的,因为当我成功地让查询按照预期工作时,我最终得到了两个条目。一个学生将会出现他们的每门课程,但是随后会有一个额外的入口以'NULL'作为课程返回。我最终分成两个查询... – LXXIII