Запрос, в котором Start_date двух таблиц не совпадают в sql

#sql #oracle #oracle-sqldeveloper

#sql #Oracle #oracle-sqldeveloper

Вопрос:

У меня есть две таблицы per_asg и xx_asg , они имеют одинаковое количество столбцов и в идеале должны иметь одинаковый номер. данных.

per_asg:

 person_id   start_date   end_date
-------------------------------------------
1           01-jan-2016  07-jan-2016
1           02-feb-2016  08-march-2016
  

xx_per_asg

 person_id   start_date   end_date
-------------------------------------
1           01-jan-2016  07-jan-2016
1           02-feb-2016  08-march-2016
1           03-feb-2016  04-sep-2016
  

Как видно на xx_per_asg, есть одна дополнительная строка с start_date '03-feb-2016' и end_date '04-sep-2016'. Я написал запрос для извлечения таких строк, но я не получаю дополнительные строки полностью :

 select start_date 
from xx_per_asg xx_per_asg, per_asg pa
where xx_per_asg.person_id = pa.person_id
  and xx_per_asg.start_date <> pa.start_date
  

Но это все равно приведет ко всему набору данных

Комментарии:

1. Вредные привычки, от которых следует отказаться: использование объединений в старом стиле — этот старый стиль списка таблиц, разделенных запятыми , был заменен на надлежащий синтаксис ANSI JOIN в стандарте ANSI- 92 SQL ( более 20 лет назад), и его использование не рекомендуется

Ответ №1:

Если вам нужны дополнительные строки, я бы ожидал запрос, более похожий на этот:

 select xx.*
from xx_per_asg xx
where not exists (select 1
                  from per_asg pa
                  where pa.person_id = xx.person_id and
                        pa.start_date = xx.start_date
                 );
  

Ответ №2:

Если в каждой таблице могут быть строки, которых нет в другой таблице, и вам нужно найти оба вида, должно сработать что-то вроде этого. Предполагая, что ни в одной из таблиц нет повторяющихся строк (например, это было бы верно, если бы у каждой из них были первичные ключи), тогда, если вы создадите union all из двух таблиц, строки, которые существуют в обеих таблицах, будут дубликатами при объединении. Те, которых нет в обеих таблицах, не будут дублироваться. Итак, после union all мы можем сгруппировать по всем столбцам и использовать HAVING COUNT(*) = 1 условие, чтобы найти строки, которые есть только в одной таблице, но отсутствуют в другой.

Небольшая настройка этого также покажет нам, в какой таблице есть «непарная» строка для каждой строки. В решении я использую max(source) (потому что мы не должны группировать по «источнику», поэтому нам нужно использовать для него агрегатную функцию), но на самом деле это max() над одним значением; это будет просто это значение.

Это решение эффективно, потому что оно не использует объединения и не использует дорогостоящую MINUS операцию (или, фактически, две MINUS операции, а также чтение каждой таблицы дважды вместо одного раза, если заданием было найти непарные строки из обеих таблиц, а не только из одной).

 select max(source), person_id, start_date, end_date
from   ( select 'per_asg'    as source, person_id, start_date, end_date from per_asg
         union all
         select 'xx_per_asg' as source, person_id, start_date, end_date from xx_per_asg
       )
group by person_id, start_date, end_date
having count(*) = 1
order by person_id, start_date, end_date    --  ORDER BY is optional
;
  

Еще одна вещь — если вы сравниваете по start_date , вы должны быть уверены, что все даты являются «чистыми датами» (без компонента времени суток); то есть компонент времени должен быть 00:00:00 . Так ли это? Если это не так, все решения нужно будет скорректировать (и они станут менее эффективными, то есть отнимут больше времени).

Ответ №3:

Если, как видно из примера, строки в обеих таблицах равны, поле за полем, вы могли бы сделать:

  select * from xx_per_asg
  minus
 select * from per_asg
  

Ответ №4:

 Select xx.startdate,xx.enddate,xx.person_id from xx_per_asg xx
LEFT OUTER JOIN per_asg per on per.person_id = xx.person_id
Where xx.start_date <> per.start_date
  

Комментарии:

1. Я не уверен, что это сработает. Если у вас есть 2 строки с датами D1 и D2 в обеих таблицах t1 и t2, они будут отображаться в результирующем наборе как t1.D1<> t2.D2 и t2.D1<>t1.D2.