.TH Matching .PP Aka 'where exists' .SH Signature .PP .RS .nf matching(left: Relation, right: Relation) \-> Relation .fi .RE .SH Examples .PP .RS .nf matching(suppliers, supplies) .fi .RE .SH Description .PP Computes a relation as a subset of \fB\fCleft\fR tuples for which at least one \fB\fCright\fR tuple would join on common attributes. .PP This operator, also known as semi\-join, can be explained through the definition below. As shown, it consists in joining \fB\fCleft\fR and \fB\fCright\fR relations and projecting the result back on \fB\fCleft\fR attributes. .PP .RS .nf def matching(left, right) project(join(left, right), left.attr_list) end matching(suppliers, supplies) .fi .RE .PP Or, in SQL terms: .PP .RS .nf SELECT left.* FROM left NATURAL JOIN right .fi .RE .PP The synonym 'where exists' comes from the fact that, since right attributes are projected away, it may seem more intuitive to think about this operator as filtering tuples from left where \fIthere exists\fP some tuple at right that \fIwould\fP join. In SQL terms: .PP .RS .nf SELECT * FROM left WHERE EXISTS (SELECT * FROM right WHERE [join condition]) .fi .RE .SH Implementation notes .PP As for (natural) \fB\fCjoin\fR, you must take care of ensuring that the list of common attributes on which the matching applies corresponds to what you want. Renamings and projections are worth having at hand when using matching. Alternatively, shortcuts can be considered. A (advanced) example below: .PP .RS .nf # Same as matching(left, right) except that only attributes in `wish` # are take into account in matching. def matching_on(left, right, wish) matching(left, project(right, wish)) end # observe here how part names have been discarded to avoid matching them # with supplier names (empty result guaranteed) matching_on(suppliers, parts, [:city]) .fi .RE