SQLRU.net
Разработка приложений баз данных

Начало » Использование СУБД » Firebird, HQbird, InterBase » Выборка значений отсутствующих во второй таблице
Выборка значений отсутствующих во второй таблице [сообщение #3914] Mon, 11 December 2023 18:46 Переход к следующему сообщению
inoremap в настоящее время не в онлайне  inoremap
Сообщений: 12
Зарегистрирован: August 2023
Junior Member
В базе данных Firebird SQL 3.0.7 есть две таблицы:
create table A (ID integer not null primary key, F integer not null);
create table B (ID integer not null primary key, F integer not null);

insert into A (ID, F) values (1, 101);
insert into A (ID, F) values (2, 102);
insert into A (ID, F) values (3, 103);

insert into B (ID, F) values (1, 101);
insert into B (ID, F) values (2, 102);
insert into B (ID, F) values (4, 104);
Индексов по F нет и добавить их нет возможности, значения F не повторяются.
Нужно получить те значения поля F из таблицы A которых нет в поле F таблицы B.
Это можно сделать запросом:
select
  A.F
from
  A
left outer join
  B on B.F = A.F
where
  B.F is null
но, т. к. нет индекса по F, то получается 3 чтения из A и 3*3 чтения из B, а хочется уложится в 3 чтения из A и 3 из B.
Сделал вариант с проходом по двум отсортированным выборкам:
execute block returns (f int)
as
  declare a_f int;
  declare b_f int;
  declare b_c cursor for (select F from B order by F);
  declare b_eof boolean;
begin
  open b_c;
  fetch b_c into :b_f;
  b_eof = row_count = 0;
  for select F from A order by F into :a_f do
  begin
    while ((a_f > b_f) and (not b_eof)) do
    begin
      fetch b_c into :b_f;
      b_eof = row_count = 0;
      if (b_eof) then
        leave;
    end
    if ((a_f < b_f) or b_eof) then
    begin
      f = a_f;
      suspend;
    end
  end
end
он вроде бы работает, но выглядит несколько громоздким, существует ли более простой способ с числом чтений не больше чем сумма записей A и B?
Re: Выборка значений отсутствующих во второй таблице [сообщение #3915 является ответом на сообщение #3914] Mon, 11 December 2023 22:39 Переход к предыдущему сообщениюПереход к следующему сообщению
sim_84 в настоящее время не в онлайне  sim_84
Сообщений: 329
Зарегистрирован: June 2022
Senior Member
Нет. В фб пока не поддерживаются ни hash/merge outer join, ни hash/merge anti join. И except тоже нет. Поэтому без индексов на больших таблицах это гиблая затея
Re: Выборка значений отсутствующих во второй таблице [сообщение #3916 является ответом на сообщение #3914] Tue, 12 December 2023 01:39 Переход к предыдущему сообщениюПереход к следующему сообщению
shavluk в настоящее время не в онлайне  shavluk
Сообщений: 82
Зарегистрирован: June 2022
Географическое положение: Одеса
Member
Без индексов, в один проход
select f
from (select f, 1 vid from a
      union all
      select f, 2 vid from b)
group by 1
having max(vid) = 1
Re: Выборка значений отсутствующих во второй таблице [сообщение #3917 является ответом на сообщение #3916] Tue, 12 December 2023 09:52 Переход к предыдущему сообщению
inoremap в настоящее время не в онлайне  inoremap
Сообщений: 12
Зарегистрирован: August 2023
Junior Member
Да, это именно то что я и хотел получить, спасибо! Небольшой минус - получается SORT(A, B) вместо SORT(A), SORT(B), но у меня в A записей на порядок меньше чем в B, так что это тем более не имеет значения.
Предыдущая тема: Новые возможности Firebird 5.0. SQL
Следующая тема: Новые возможности Firebird 5.0: Часть 3, SKIP LOCKED
Переход к форуму:
  


Текущее время: Fri Nov 15 04:40:34 GMT+3 2024

Общее время, затраченное на создание страницы: 0.00648 секунд