Часто, когда мы пытаемся перейти непосредственно к аф inal query, это может оказаться намного более сложным, что должно - если оно вообще работает. Как правило, не помешает просто выполнить прямое соединение на рассматриваемых таблицах и посмотреть на результаты. Если ничего другого, вы проверить соединение является правильным:
with
Master(ID, Name)as(
select 1, 'John' from dual union all
select 2, 'David' from dual union all
select 3, 'Simon' from dual union all
select 4, 'Jessica' from dual union all
select 5, 'Becky' from dual
),
Trans(MasterID, EffDate, Action)as(
select 1, date '2015-08-28', 'IN' from dual union all
select 1, date '2015-09-03', 'IN' from dual union all
select 2, date '2015-08-17', 'IN' from dual union all
select 2, date '2015-10-01', 'IN' from dual union all
select 4, date '2015-09-05', 'IN' from dual
)
select *
from Master m
join Trans t
on t.MasterID = m.ID;
(Извините за переименование некоторых из ваших полей.) Я, случается, есть Oracle в тот момент, вы можете использовать все, что у вас есть. Вероятно, этот код будет работать с любой системой без Oracle, просто удалив «из двойника» из кода CTE.
Теперь давайте продолжим критерии соединения, но давайте сделаем это, чтобы сгенерировать данные, которые мы не делаем хотим видеть.
join Trans t
on t.MasterID = m.ID
and t.EffDate >= date '2015-09-01'
and t.EffDate < date '2015-10-01';
Я жестко закодированы значения дат, но это лучший формат для использования, чтобы получить «в течение месяца ...» диапазоны. Каждое значение выбирается с первого тика в первый день месяца до последнего последнего тика до первого дня следующего месяца. Конечно, вы захотите сохранить эти значения в переменных или создать их «на лету».
Итак, теперь мы видим только две транзакции, которые произошли во время Сентябрь. Очевидным следующим шагом является выполнение внешнего соединения, поэтому мы получаем все другие основные записи, которые не совпадают.
left join Trans t
Теперь у нас есть все записи, которые мы хотим, плюс два, которые мы не хотим. Поскольку они единственные, которые соответствуют ограничениям по дате, мы добавляем критерии фильтрации для их удаления. Вот окончательный запрос:
select m.*
from Master m
left join Trans t
on t.MasterID = m.ID
and t.EffDate >= date '2015-09-01'
and t.EffDate < date '2015-10-01'
where t.MasterID is null;
Простой на самом деле. Как только вы это сделаете несколько раз, вы сможете перейти к готовому запросу без промежуточных шагов. Тем не менее, не мешает выполнить промежуточные шаги и смотреть на выходы по пути. Любые недостатки в логике будут пойманы ранее, когда их можно будет легко устранить.
Какой у вас dbms? (Многие продукты далеки от соответствия ANSI SQL, когда дело доходит до даты/времени ...) – jarlh
Это не вопрос даты, это проблема, это факт, что некоторые m строк не имеют соответствующих строк t вообще, а некоторые из них находятся за пределами диапазон дат. T-sql для VistaDB является фактическим диалектом. –