Мнезийный эквивалент SQL NOT IN - PullRequest
3 голосов
/ 19 февраля 2012

У меня есть две записи:

-record(foo, {timestamp, name}).
-record(bar, {timestamp, name}).

И я хотел бы выполнить запрос Mnesia, который имитирует следующий запрос SQL

SELECT f.* FROM foo f WHERE f.timestamp NOT IN ( SELECT b.timestamp FROM boo b)

Каким будет эффективный эквивалент Mnesia?

1 Ответ

2 голосов
/ 20 февраля 2012

Хороший вопрос!Теперь я подумал о двух способах.Один, где мы используем qlc, а другой, где мы используем mnesia's own table iteration methods with accumulators.Вот первый вариант:

%% Here i use 'qlc', with a guard
%% which ensures that the timestamp
%% in the given 'foo record'
%% does NOT exist in table 'bar'<br>
query()->
    Is_not_in_bar = fun(Stamp)-> 
                     case mnesia:dirty_read({bar,Stamp}) of
                        [] -> true;
                        _ -> false
                     end
                end,<br>
    Q = qlc:q([R || R <- mnesia:table(foo),<br>                         Is_not_in_bar(R#foo.timestamp) == true])),
    Fun = fun(QH)-> qlc:e(QH) end,
    mnesia:activity(transaction,Fun,[Q],mnesia_frag).

Другой вариант - итерация таблицы foo при перекрестной ссылке на каждую метку времени в таблице bar.Если он не найден в bar, то он добавляется к накопленной сумме.посмотрите на это ниже

%% Here i iterate table 'foo'
%% for each record i find,
%% i try to cross reference
%% its timestamp in table 'bar'
%% If its not found, then i add that
%% 'foo record' into the Buffer
%% I accumulate this Buffer until
%% the entire table 'foo' has been 
%% traversed<br>
query_vsn2()->
    Iterator = fun(#foo{timestamp = T} = Rec,Buffer)->
                    NewBuffer = case mnesia:dirty_read({bar,T}) of
                                    [] -> [Rec|Buffer];
                                    _ -> Buffer
                                end,
                    NewBuffer
                end,
    Find = fun(Loop)-> mnesia:foldl(Loop,[],foo) end,
    mnesia:activity(transaction,Find,[Iterator],mnesia_frag).
Я думаю, в зависимости от размера таблицы, приложения и предпочтений пользователя, каждая из этих функций будет иметь последствия.Однако попробуйте оба из них и посмотрите, какой из них хорошо вписывается в ваше приложение.Хорошо, что это полностью работа по чтению, без записи, так что я надеюсь быть достаточно эффективной.Удачи!
...