Mnesia相当于SQL NOT IN

时间:2012-02-19 08:24:44

标签: erlang mnesia

我有两条记录:

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

我想执行一个模仿以下SQL查询的Mnesia查询

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

什么是有效的Mnesia等价物?

1 个答案:

答案 0 :(得分:2)

好问题!现在,我想到了两种方式。我们使用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'
query()-> Is_not_in_bar = fun(Stamp)-> case mnesia:dirty_read({bar,Stamp}) of [] -> true; _ -> false end end,
Q = qlc:q([R || R <- mnesia:table(foo),
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
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).
我想根据表大小,应用程序和用户偏好,这些功能中的每一个都会产生影响。但是,试试它们,看看哪一个很好地融入你的应用程序。好消息是,这完全是一个读取工作,没有写入,所以我期望足够高效。成功!