我有以下问题sql查询我需要帮助,因为我无法理解它。
我正在尝试检索我的预订表的课程列表,唯一的问题是我需要确保课程仍然有效,因为我有一个可以做两件事的覆盖表。
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
答案 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