多重标准或混淆

时间:2016-06-20 14:48:10

标签: sql

我有以下问题sql查询我需要帮助,因为我无法理解它。

我正在尝试检索我的预订表的课程列表,唯一的问题是我需要确保课程仍然有效,因为我有一个可以做两件事的覆盖表。

  1. 当一个班级去旅行时,我想覆盖显示的课程,所以我已经包含了一个开始日期和结束日期。如果课程属于这个范围而不是我不想取回课程。
  2. 2我的覆盖表中有一个isNoMoreLesson布尔字段。如果课程已经完成,我想永久排除以前预订课程的绊倒

    SELECT DISTINCT LessonSubset.SubjectName, 
    LessonSubset.Day, 
    LessonSubset.StartTime, 
    LessonSubset.EndTime, 
    LessonSubset.fk_PeriodInformationID 
    
    FROM LessonSubset
    
    LEFT JOIN OverrideLesson ON 
    (LessonSubset.fk_ResourceID = OverrideLesson.fk_ResourceID AND 
    LessonSubset.fk_PeriodInformationID = OverrideLesson.fk_PeriodInformationID) 
    
    WHERE LessonSubset.fk_ResourceID = ‘XABCDE' AND LessonSubset.Day = ‘Mon' AND
    (OverrideLesson.isNoMoreLesson != 1 OR booking_date < OverrideLesson.EndDate AND
    booking_date< OverrideLesson.StartDate) 
    
    ORDER BY  LessonSubset.Day ASC
    

2 个答案:

答案 0 :(得分:1)

如果进行左连接,则不应在左连接表上放置WHERE子句(或者您将获得与内连接相同的结果)。

所以要么你想要一个左连接(而不是在左连接子句中把overrideLesson上的子句放在一起),或者做一个内连接。

由于您只获取LessonSubset中的数据并希望根据OverrideLesson限制排除数据,我认为您需要内部联接。

然后,你有&#34; OR&#34;和&#34; AND&#34;,如果你不处理优先顺序,你可能会给你一些奇怪的结果(你应该把括号括起来)。我猜(但不是很清楚)你的AND / OR逻辑不是你想要的。

所以

SELECT DISTINCT 
  LessonSubset.SubjectName, 
  LessonSubset.Day, 
  LessonSubset.StartTime, 
  LessonSubset.EndTime, 
  LessonSubset.fk_PeriodInformationID 

FROM LessonSubset

LEFT JOIN OverrideLesson ON 
  LessonSubset.fk_ResourceID = OverrideLesson.fk_ResourceID AND 
  LessonSubset.fk_PeriodInformationID = OverrideLesson.fk_PeriodInformationID AND
  --include the restrictions in the left join, and change the "and / or logic"
  OverrideLesson.isNoMoreLesson != 1 AND 
  --take only if booking_date is out of range
  (booking_date > OverrideLesson.EndDate OR booking_date < OverrideLesson.StartDate)

WHERE LessonSubset.fk_ResourceID = 'XABCDE' AND LessonSubset.Day = 'Mon'

ORDER BY  LessonSubset.Day ASC

编辑: 如果你想排除一些结果,使用NOT EXISTS条款可能会更清楚

SELECT DISTINCT 
  ls.SubjectName, 
  ls.Day, 
  ls.StartTime, 
  ls.EndTime, 
  ls.fk_PeriodInformationID 

FROM LessonSubset ls
WHERE ls.fk_ResourceID = 'XABCDE' AND ls.Day = 'Mon'
AND NOT EXISTS (SELECT NULL 
                FROM OverrideLesson ol
                WHERE 
                ls.fk_ResourceID = ol.fk_ResourceID AND 
                ls.fk_PeriodInformationID = ol.fk_PeriodInformationID AND
                ol.isNoMoreLesson != 1 AND 
                (booking_date > ol.EndDate OR booking_date < ol.StartDate))

ORDER BY  ls.Day ASC

答案 1 :(得分:0)

这是一个简单的模式,它将向您展示如何在表之间匹配记录时使用LEFT JOIN来排除。您的所有联接要求应位于联接的“ON”部分,因为其他答案/评论已提及其他要求。如果你没有将它们放在那个部分并且你将它们留在where子句中,那么你必须考虑空值,否则你将限制你的查询并基本上将你的结果变成与inner join相同的结果。唯一的例外是将未经匹配的字段(例如第2个表的主键)放在null的where语句中,并使条件等于NULL。这是为了排除您不想要的记录。如果你想要一切,那么不要用where子句限制。

CREATE TABLE dbo.T1 (
    Id INT IDENTITY(1,1)
    ,C CHAR(1)
)

CREATE TABLE dbo.T2 (
    PKId INT
)

INSERT INTO dbo.T1 (C)
VALUES ('A'),('B'),('C'),('D')

INSERT INTO dbo.T2 (PKId)
VALUES (1),(4)

SELECT *
FROM
  dbo.T1 t1
  LEFT JOIN dbo.T2 t2
  ON t1.Id = t2.PKId
 WHERE
   t2.PKId IS NULL