Как оптимизировать этот запрос? - PullRequest
1 голос
/ 08 августа 2011

У меня есть таблицы: A (ID_A, VALID_FROM, ДАННЫЕ ...) B (ID_B, ID, T1, T2, T3, DATE)

Таблица A может содержать исторические данные (например, данные действительны для данного периода) Мне нужно выбрать записи из таблицы B, объединенной с соответствующими записями из таблицы A (из таблицы A мне нужна строка, где b.id = a.id_a и запись действительна в b.date)

select * 
from B, (select * from (select * from A where a.id_a = b.id and a.valid_from <= b.date order by valid_from desc) where rownum = 1)
where b.id = a.id_a

Ответы [ 3 ]

2 голосов
/ 08 августа 2011
1 голос
/ 08 августа 2011

Это не намного более оптимально, но, вероятно, более читабельно:

select *  
from A a, B b
Where 
a.id_a = b.id 
and a.valid_from = (select max(valid_from) 
                    from A 
                    where id_a = b.id 
                    and valid_from <= b.date)
order by valid_from desc

Я уже видел эту проблему раньше, и лучший из известных мне способов ее оптимизации - поместить столбец valid_to в таблицу A.

Для последней записи в ней должна быть указана самая большая дата, которую может обработать Oracle.
Всякий раз, когда вы создаете более новую версию записи, обновляйте ее во время создания новой записи (минус миллисекунда, чтобы избежать дублирования), чтобы у вас было что-то вроде этого:

ID Valid_from                Valid_to
1  01/01/2011 12.34.56.0000  02/01/2011 12.34.56.0000
1  02/01/2011 12.34.56.0001  03/01/2011 12.34.56.0000
1  03/01/2011 12.34.56.0001  31/12/9999 23.59.59.9999

Тогда вы можете запросить это так:

select *  
from A a, B b
Where 
a.id_a = b.id 
and b.date between a.valid_from and a.valid_to
order by valid_from desc

С индексом по столбцам даты производительность должна быть в порядке ..

0 голосов
/ 08 августа 2011

Я взял ответ StevieG и расширил его. Без столбца valid_to есть сложные подзапросы для записи. Я бы предложил использовать аналитическую функцию LEAD, чтобы найти конец текущего периода действия и работать с этим. Это альтернатива подзапросам и столбцу valid_to.

Аналитическая функция LEAD просматривает строки в текущем наборе данных, находит следующую дату valid_from и использует ее как конец текущего периода.

Мой запрос показан ниже. Он включает предоставленные вами образцы данных в предложении with.

with table_a as (
  select 1 as id, 'XXX1' as data, date '2009-01-01' as valid_from from dual union all
  select 1 as id, 'XXX2' as data, date '2009-05-30' as valid_from from dual union all
  select 1 as id, 'XXX3' as data, date '2010-01-11' as valid_from from dual union all
  select 2 as id, 'YYY' as data, date '1999-01-01' as valid_from from dual
),
table_b as (
  select 1 as id, 1 as id_a, date '2009-02-01' as date_col from dual union all
  select 2 as id, 2 as id_a, date '2009-09-12' as date_col from dual union all
  select 3 as id, 1 as id_a, date '2009-06-30' as date_col from dual
)
select *
from table_b b
  join (
    select 
      id, 
      valid_from, 
      lead(valid_from, 1, date '9999-12-31') over (partition by a.id order by a.valid_from) as valid_to
    from table_a a
) a on (a.id = b.id_a)
where 
  a.valid_from <= b.date_col and 
  b.date_col < a.valid_to
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...