我有两条记录:
-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等价物?
答案 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).