2016-06-20 4 views
0

У меня есть следующий запрос sql проблемы. Мне нужна помощь, так как я не могу обойти ее.Множество критериев или недоразумений

Я пытаюсь получить список уроков для моей таблицы бронирования, единственное, что мне нужно, чтобы убедиться, что уроки по-прежнему актуальны, поскольку у меня есть таблица переопределения, которая может делать две вещи.

  1. Когда класс отправляется в путешествие, я хочу переопределить уроки от отображения, поэтому я включил дату начала и дату окончания. Если уроки попадают в этот диапазон, я не хочу извлекать уроки.

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 
+1

Вы можете показать некоторые данные образца и ожидаемый результат? –

+0

Это возврат неверных результатов или ошибок? Я принимаю неверные результаты ... если это так, вы получаете слишком много результатов или недостаточно? –

+0

У меня нет никаких результатов, на всех. – JK36

ответ

1

Если вы делаете левое соединение, вы не должны ставить ИНЕК на левую присоединяемую таблице (или вы получите тот же результат, внутреннее соединение).

Таким образом, либо вы хотите, чтобы левое соединение (чем положить предложения в overrideLesson в предложение левого соединения), или сделать внутреннее соединение.

Поскольку вы получаете только данные из LessonSubset и хотите исключить данные в зависимости от ограничений OverrideLesson, я думаю, вам нужно внутреннее соединение.

Затем у вас есть сочетание «ИЛИ» и «И», что может дать вам некоторые странные результаты, если вы не позаботитесь о порядке приоритета (скорее всего, вы должны скопировать скобки). И я думаю (но это не так понятно), что ваша логика 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 

EDIT: Если вы хотите исключить некоторые результаты, возможно, было бы понятнее использовать 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 
+0

Этот последний фрагмент отсутствует WHERE OverrideLesson.PrimaryKeyField имеет значение null. OP попросил не показывать их, поэтому я бы предпочел, чтобы вы исключали и удаляли любые согласованные записи между LessonSubset и OverrideLesson. – Matt

+0

@Matt. Хорошо, я пишу об этом в своем ответе: в этом случае внутреннего соединения будет достаточно (или лучше, используйте предложение NOT EXISTS вместо соединения) –

+0

Нет, потому что он хотел исключить/удалить совпадения из набора данных. Поэтому мое понимание вопроса должно быть возвращено только записям, которые не были превышены. При выполнении левого соединения, если нет совпадения, первичный ключ в правой стороне таблицы будет NULL, если нет совпадения. Таким образом, вы устраняете все записи, которые совпадают между таблицами, которые он не стал внутренним соединением. – Matt

0

Вот простой шаблон, который покажет вам идею о том, как использовать LEFT JOIN, чтобы исключить, когда записи сопоставляются между таблицами. Все ваши требования к соединению должны быть в разделе «ON» объединений, поскольку другие ответы/комментарии упомянули другое. Если вы не поместите их в этот раздел, и вы оставите их в предложении where, вам придется учитывать нулевые значения, иначе вы ограничите свой запрос и по существу превратите свои результаты в то же самое, что и inner join. Единственное исключение - разместить поле, которое вы всегда знаете, будет null, если не согласовано (например, первичный ключ 2-й таблицы) в оператор 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 
Смежные вопросы