可以单遍构建内存结构的完整联接(不使用sql!)

时间:2018-09-08 21:12:19

标签: join rust nested-loops relational-algebra relational

我正在构建一个内存中的柱状关系引擎。为了提取值,我想进行后期实现,在那儿我收集找到匹配项的位置/索引,最后收集值。

现在实现联接,我看不到如何涵盖所有其他情况的通用联接算法。向左,向右和向内很容易,而向左/向右不容易。这是我幼稚的嵌套循环实现:

vonc@vonca:/mnt/d/git/tests/aa$ echo $(git write-tree)
4b825dc642cb6eb9a060e54bf8d69288fbee4904

vonc@vonca:/mnt/d/git/tests/aa$ echo "$(git write-tree)"
4b825dc642cb6eb9a060e54bf8d69288fbee4904

现在,问题是,我可以找到何时在右侧找不到左侧,但没有另一遍就找不到相反的一侧:

pub fn join(&self, compare:&BoolExpr) -> JoinPos
{
    //Allocate at least for inner joins...
    let total = cmp::max(self.left.len(), self.right.len());

    let mut cols_left  = Vec::with_capacity(total);
    let mut cols_right = Vec::with_capacity(total);
    let mut found = false;

    while !self.left.eof() {
        let left = self.left.tuple();
        while !self.right.eof() {
            let right = self.right.tuple();
            if compare(&left, &right) {
                //A match found. Record positions of both cursors
                cols_left.push(self.left.pos() as isize);
                cols_right.push(self.right.pos() as isize);
                found = true;
            }
            self.right.next();
        }
        //Not found a single match at the right cursor..
        if !found {
            cols_left.push(self.left.pos() as isize);
            cols_right.push(-1);
        }
        found = false;
        self.left.next();
        self.right.first();
    }

    JoinPos {
        left:cols_left,
        right:cols_right,
    }
}

感谢@philipxy,我有一个可行的解决方案:

Input:
L= [1, 2, 3]
R= [2, 3, 4]

Result. It capture the positions that match. -1 if not found
L | R
======
1   -1
2   1
3   2
-1  3

1 个答案:

答案 0 :(得分:1)

完全联接返回内部联接元组,并以空值扩展不匹配的左表元组;并以空值扩展的不匹配右表元组。

当前,您的代码输出左连接元组。外部循环的每次迭代输出的都是内部联接中的更多元组,或者它输出的左表元组的空扩展名与任何右表元组都不匹配。要输出完全联接元组,您还必须输出与任何左表元组都不匹配的每个右表元组的null扩展。您可以执行以下操作:在循环之前定义一个set变量。最终它将包含与任何左表元组都不匹配的右表元组的所有位置/索引。在module SessionsHelper # Logs in the given user. def log_in(parent) session[:parent_id] = parent.id end def log_in(teacher) session[:teacher_id] = teacher.id end # Returns the current logged-in user (if any). def current_teacher @current_teacher ||= Teacher.find_by(id: session[:teacher_id]) end def current_parent @current_parent ||= Parent.find_by(id: session[:parent_id]) end # Returns true if the user is logged in, false otherwise. def logged_in?(teacher) !current_teacher.nil? end def logged_in?(parent) !current_parent.nil? end def log_out(teacher) session.delete(:teacher_id) @current_teacher = nil end def log_out(parent) session.delete(:parent_id) @current_parent = nil end end 之前,如果它是外循环的第一次迭代,则将正确的元组位置/索引插入到集合中。在if compare的嵌套块内,从集合中删除正确的元组位置/索引。