2015-09-21 2 views
0

Не могу понять, что я хочу: все строки в главной таблице, которые не имеют соответствующих строк транзакций в таблице транзакций, для данного диапазона дат. Пример: главная таблица м:SQL, где нет совпадений * для диапазона дат * в таблице транзакций

id Name 
1 John 
2 David 
3 Simon 
4 Jessica 
5 Becky 

таблица транзакций т

id parent date  action 
1 1  2015-08-28 IN 
2 1  2015-09-03 IN 
3 2  2015-08-17 IN 
4 2  2015-10-01 IN 
5 4  2015-09-05 IN 

Я хочу, чтобы все эти записи в м, которые не имеют каких-либо сделок в сентябре: так что я должен получить m.id 2,3 , 5

1 does not match: events in september 
2 matches: events but none in september 
3 matches: no events at all 
4 does not match: events in september 
5 matches: No events at all 

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

+0

Какой у вас dbms? (Многие продукты далеки от соответствия ANSI SQL, когда дело доходит до даты/времени ...) – jarlh

+0

Это не вопрос даты, это проблема, это факт, что некоторые m строк не имеют соответствующих строк t вообще, а некоторые из них находятся за пределами диапазон дат. T-sql для VistaDB является фактическим диалектом. –

ответ

1

Часто, когда мы пытаемся перейти непосредственно к аф 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; 

Простой на самом деле. Как только вы это сделаете несколько раз, вы сможете перейти к готовому запросу без промежуточных шагов. Тем не менее, не мешает выполнить промежуточные шаги и смотреть на выходы по пути. Любые недостатки в логике будут пойманы ранее, когда их можно будет легко устранить.

0

выберите все мастер, присоединитесь к транзакции, сгруппированной по родительскому (что приводит к 0..1 строке на главную запись).

если нет записи о транзакции, t.parent будет null, что не означает транзакции для этой основной записи.

если есть данные сделки, вы найдете счет в t.a, если некоторые из них в сентябре, вы найдете их в t.m9

, если вы хотите, чтобы все мастера без какой-либо сделки, вы будете фильтра, где t.parent is null

, если вы хотите, чтобы все мастера без сделки в сентябре, вы будете фильтровать где t.parent is null or t.m9=0

select m.id, m.name, 
    , t.a, t.m9 
from master_table m 
left join (select a = count(*) 
       , m9 = count(case when datepart(Month, t.date) = 9 then 1 end) 
       , t.parent 
      from transaction_table t 
      group by t.parent 
     ) t on t.parent = m.id 
where t.parent is null or t.m9=0 
+0

Итак, это должно быть 2 вопроса? Я думал, что чего-то не хватает, и был разумный способ получить обе стороны проблемы в одном запросе –

+0

, это один запрос. –

+0

И выше другое: q1: те, у которых нет записей в t, q2: те, у которых есть записи в t, которые не находятся в диапазоне дат. –

Смежные вопросы